diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index fca2803d533ab7..4ff6f4254361ca 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -15,7 +15,7 @@ ] }, "microsoft.dotnet.xharness.cli": { - "version": "8.0.0-prerelease.23272.1", + "version": "8.0.0-prerelease.23279.1", "commands": [ "xharness" ] diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 6cff61033ba5bd..22648cbe1e4e8d 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -96,3 +96,8 @@ /docs/project/list-of-diagnostics.md @jeffhandley /src/libraries/Common/src/System/Obsoletions.cs @jeffhandley + +# Area ownership and repo automation +/docs/area-owners.* @jeffhandley +/docs/issue*.md @jeffhandley +/.github/fabricbot.json @jeffhandley diff --git a/.github/fabricbot.json b/.github/fabricbot.json index e637dff84057ca..0d44054e037e81 100644 --- a/.github/fabricbot.json +++ b/.github/fabricbot.json @@ -2595,7 +2595,7 @@ "subCapability": "IssueCommentResponder", "version": "1.0", "config": { - "taskName": "Replace `needs-author-action` label with `needs-further-triage` label when the author comments on an issue", + "taskName": "Replace `needs-author-action` label with `needs-further-triage` label when the author comments on an issue that is not still untriaged", "actions": [ { "name": "addLabel", @@ -2637,6 +2637,74 @@ "label": "needs-author-action" } }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "untriaged" + } + } + ] + }, + { + "name": "isOpen", + "parameters": {} + } + ] + } + } + }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssueCommentResponder", + "version": "1.0", + "config": { + "taskName": "Remove `needs-author-action` label when the author comments on an `untriaged` issue", + "actions": [ + { + "name": "removeLabel", + "parameters": { + "label": "needs-author-action" + } + } + ], + "eventType": "issue", + "eventNames": [ + "issue_comment" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isAction", + "parameters": { + "action": "created" + } + }, + { + "name": "isActivitySender", + "parameters": { + "user": { + "type": "author" + } + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "untriaged" + } + }, { "name": "isOpen", "parameters": {} @@ -4101,6 +4169,77 @@ } } ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" + } + } + ] + } + ] } ] } @@ -4242,6 +4381,77 @@ } } ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" + } + } + ] + } + ] } ] } @@ -4356,47 +4566,52 @@ } }, { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "and", "operands": [ { - "name": "isInMilestone", + "name": "isOpen", "parameters": {} - } - ] - }, - { - "operator": "not", - "operands": [ + }, { - "name": "hasLabel", - "parameters": { - "label": "needs-author-action" - } - } - ] - }, - { - "operator": "not", - "operands": [ + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + }, { - "name": "hasLabel", - "parameters": { - "label": "api-ready-for-review" - } - } - ] - } - ] - } - } - }, - { - "taskSource": "fabricbot-config", - "taskType": "trigger", + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] + } + ] + } + ] + } + } + }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", "capabilityId": "IssueResponder", "subCapability": "IssueCommentResponder", "version": "1.0", @@ -4434,37 +4649,42 @@ } }, { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "and", "operands": [ { - "name": "isInMilestone", + "name": "isOpen", "parameters": {} - } - ] - }, - { - "operator": "not", - "operands": [ + }, { - "name": "hasLabel", - "parameters": { - "label": "needs-author-action" - } - } - ] - }, - { - "operator": "not", - "operands": [ + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + }, { - "name": "hasLabel", - "parameters": { - "label": "api-ready-for-review" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] } ] } @@ -4512,37 +4732,42 @@ } }, { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "and", "operands": [ { - "name": "isInMilestone", + "name": "isOpen", "parameters": {} - } - ] - }, - { - "operator": "not", - "operands": [ + }, { - "name": "hasLabel", - "parameters": { - "label": "needs-author-action" - } - } - ] - }, - { - "operator": "not", - "operands": [ + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + }, { - "name": "hasLabel", - "parameters": { - "label": "api-ready-for-review" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] } ] } @@ -4590,37 +4815,42 @@ } }, { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "and", "operands": [ { - "name": "isInMilestone", + "name": "isOpen", "parameters": {} - } - ] - }, - { - "operator": "not", - "operands": [ + }, { - "name": "hasLabel", - "parameters": { - "label": "needs-author-action" - } - } - ] - }, - { - "operator": "not", - "operands": [ + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + }, { - "name": "hasLabel", - "parameters": { - "label": "api-ready-for-review" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] } ] } @@ -4632,23 +4862,22 @@ "taskSource": "fabricbot-config", "taskType": "trigger", "capabilityId": "IssueResponder", - "subCapability": "PullRequestResponder", + "subCapability": "IssuesOnlyResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Adam / David - PRs] Closed, Merged, or Moved", + "taskName": "[Area Pod: Adam / David - Issue Triage] Excluded", "actions": [ { - "name": "moveToProjectColumn", + "name": "removeFromProject", "parameters": { - "projectName": "Area Pod: Adam / David - PRs", - "columnName": "Done", + "projectName": "Area Pod: Adam / David - Issue Triage", "isOrgProject": true } } ], - "eventType": "pull_request", + "eventType": "issue", "eventNames": [ - "pull_request" + "issues" ], "conditions": { "operator": "and", @@ -4656,149 +4885,48 @@ { "name": "isInProject", "parameters": { - "projectName": "Area Pod: Adam / David - PRs", + "projectName": "Area Pod: Adam / David - Issue Triage", "isOrgProject": true } }, { - "operator": "not", + "operator": "or", "operands": [ { - "name": "isInProjectColumn", + "name": "hasLabel", "parameters": { - "projectName": "Area Pod: Adam / David - PRs", - "columnName": "Done", - "isOrgProject": true + "label": "os-android" } - } - ] - }, - { - "operator": "or", - "operands": [ + }, { - "operator": "not", - "operands": [ - { - "name": "isOpen", - "parameters": {} - } - ] + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } }, { - "operator": "and", - "operands": [ - { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "area-Extensions-Caching" - } - } - ] - }, - { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "area-Extensions-FileSystem" - } - } - ] - }, - { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Console" - } - } - ] - }, - { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Diagnostics.Process" - } - } - ] - }, - { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Formats.Asn1" - } - } - ] - }, - { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Formats.Cbor" - } - } - ] - }, - { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "area-System.IO" - } - } - ] - }, - { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "area-System.IO.Hashing" - } - } - ] - }, - { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Linq.Parallel" - } - } - ] - }, - { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Security" - } - } - ] - } - ] + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" + } } ] } @@ -4810,16 +4938,15 @@ "taskSource": "fabricbot-config", "taskType": "trigger", "capabilityId": "IssueResponder", - "subCapability": "PullRequestResponder", + "subCapability": "IssuesOnlyResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Adam / David - PRs] New PR Needs Champion", + "taskName": "[Area Pod: Adam / David - PRs] Moved to Another Area", "actions": [ { - "name": "addToProject", + "name": "removeFromProject", "parameters": { "projectName": "Area Pod: Adam / David - PRs", - "columnName": "Needs Champion", "isOrgProject": true } } @@ -4832,85 +4959,48 @@ "operator": "and", "operands": [ { - "name": "isAction", - "parameters": { - "action": "opened" - } - }, - { - "operator": "or", + "operator": "and", "operands": [ { - "name": "hasLabel", - "parameters": { - "label": "area-Extensions-Caching" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-Extensions-FileSystem" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Console" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Diagnostics.Process" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Formats.Asn1" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Formats.Cbor" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.IO" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Caching" + } + } + ] }, { - "name": "hasLabel", - "parameters": { - "label": "area-System.IO.Hashing" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-FileSystem" + } + } + ] }, { - "name": "hasLabel", - "parameters": { - "label": "area-System.Linq.Parallel" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Console" + } + } + ] }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Security" - } - } - ] - }, - [ - [ { "operator": "not", "operands": [ { - "name": "isAssignedToUser", + "name": "hasLabel", "parameters": { - "user": "adamsitnik" + "label": "area-System.Diagnostics.Process" } } ] @@ -4919,22 +5009,20 @@ "operator": "not", "operands": [ { - "name": "isActivitySender", + "name": "hasLabel", "parameters": { - "user": "adamsitnik" + "label": "area-System.Formats.Asn1" } } ] - } - ], - [ + }, { "operator": "not", "operands": [ { - "name": "isAssignedToUser", + "name": "hasLabel", "parameters": { - "user": "jozkee" + "label": "area-System.Formats.Cbor" } } ] @@ -4943,39 +5031,60 @@ "operator": "not", "operands": [ { - "name": "isActivitySender", + "name": "hasLabel", "parameters": { - "user": "jozkee" + "label": "area-System.IO" } } ] - } - ] - ], - { - "operator": "or", - "operands": [ + }, { "operator": "not", "operands": [ { - "name": "isInProject", + "name": "hasLabel", "parameters": { - "projectName": "Area Pod: Adam / David - PRs", - "isOrgProject": true + "label": "area-System.IO.Hashing" } } ] }, { - "name": "isInProjectColumn", - "parameters": { - "projectName": "Area Pod: Adam / David - PRs", - "columnName": "Done", - "isOrgProject": true - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Linq.Parallel" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Security" + } + } + ] } ] + }, + { + "name": "isAction", + "parameters": { + "action": "unlabeled" + } + }, + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "isOrgProject": true + } } ] } @@ -4988,20 +5097,13 @@ "subCapability": "PullRequestResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Adam / David - PRs] Updated PR Needs Champion", + "taskName": "[Area Pod: Adam / David - PRs] Closed, Merged, or Moved", "actions": [ { - "name": "removeFromProject", - "parameters": { - "projectName": "Area Pod: Adam / David - PRs", - "isOrgProject": true - } - }, - { - "name": "addToProject", + "name": "moveToProjectColumn", "parameters": { "projectName": "Area Pod: Adam / David - PRs", - "columnName": "Needs Champion", + "columnName": "Done", "isOrgProject": true } } @@ -5014,20 +5116,189 @@ "operator": "and", "operands": [ { - "name": "isOpen", - "parameters": {} + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "isOrgProject": true + } }, { "operator": "not", "operands": [ { - "name": "isAction", + "name": "isInProjectColumn", "parameters": { - "action": "opened" + "projectName": "Area Pod: Adam / David - PRs", + "columnName": "Done", + "isOrgProject": true } } ] }, + { + "operator": "or", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isOpen", + "parameters": {} + } + ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Caching" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-FileSystem" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Console" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.Process" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Formats.Asn1" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Formats.Cbor" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO.Hashing" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Linq.Parallel" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Security" + } + } + ] + } + ] + } + ] + } + ] + } + } + }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "taskName": "[Area Pod: Adam / David - PRs] New PR Needs Champion", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "columnName": "Needs Champion", + "isOrgProject": true + } + } + ], + "eventType": "pull_request", + "eventNames": [ + "pull_request" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isAction", + "parameters": { + "action": "opened" + } + }, { "operator": "or", "operands": [ @@ -5093,39 +5364,67 @@ } ] }, - { - "operator": "not", - "operands": [ - { - "name": "isAssignedToUser", - "parameters": { - "user": "adamsitnik" - } - } - ] - }, - { - "operator": "not", - "operands": [ - { - "name": "isAssignedToUser", - "parameters": { - "user": "jozkee" - } - } - ] - }, - { - "operator": "or", - "operands": [ + [ + [ { "operator": "not", "operands": [ { - "name": "isInProject", + "name": "isAssignedToUser", "parameters": { - "projectName": "Area Pod: Adam / David - PRs", - "isOrgProject": true + "user": "adamsitnik" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "isActivitySender", + "parameters": { + "user": "adamsitnik" + } + } + ] + } + ], + [ + { + "operator": "not", + "operands": [ + { + "name": "isAssignedToUser", + "parameters": { + "user": "jozkee" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "isActivitySender", + "parameters": { + "user": "jozkee" + } + } + ] + } + ] + ], + { + "operator": "or", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "isOrgProject": true } } ] @@ -5139,6 +5438,77 @@ } } ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" + } + } + ] + } + ] } ] } @@ -5151,7 +5521,7 @@ "subCapability": "PullRequestResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Adam / David - PRs] Adam Assigned as Champion", + "taskName": "[Area Pod: Adam / David - PRs] Updated PR Needs Champion", "actions": [ { "name": "removeFromProject", @@ -5164,7 +5534,7 @@ "name": "addToProject", "parameters": { "projectName": "Area Pod: Adam / David - PRs", - "columnName": "Champion: Adam", + "columnName": "Needs Champion", "isOrgProject": true } } @@ -5180,6 +5550,17 @@ "name": "isOpen", "parameters": {} }, + { + "operator": "not", + "operands": [ + { + "name": "isAction", + "parameters": { + "action": "opened" + } + } + ] + }, { "operator": "or", "operands": [ @@ -5246,63 +5627,1062 @@ ] }, { - "operator": "or", + "operator": "not", "operands": [ { "name": "isAssignedToUser", "parameters": { "user": "adamsitnik" } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "isAssignedToUser", + "parameters": { + "user": "jozkee" + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "isOrgProject": true + } + } + ] }, { - "operator": "and", + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "columnName": "Done", + "isOrgProject": true + } + } + ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" + } + } + ] + } + ] + } + ] + } + } + }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "taskName": "[Area Pod: Adam / David - PRs] Adam Assigned as Champion", + "actions": [ + { + "name": "removeFromProject", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "isOrgProject": true + } + }, + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "columnName": "Champion: Adam", + "isOrgProject": true + } + } + ], + "eventType": "pull_request", + "eventNames": [ + "pull_request" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isOpen", + "parameters": {} + }, + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Caching" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-FileSystem" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Console" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.Process" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Formats.Asn1" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Formats.Cbor" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO.Hashing" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Linq.Parallel" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Security" + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "isAssignedToUser", + "parameters": { + "user": "adamsitnik" + } + }, + { + "operator": "and", + "operands": [ + { + "name": "isAction", + "parameters": { + "action": "opened" + } + }, + { + "name": "isActivitySender", + "parameters": { + "user": "adamsitnik" + } + } + ] + } + ] + }, + { + "operator": "or", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "isOrgProject": true + } + } + ] + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "columnName": "Needs Champion", + "isOrgProject": true + } + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "columnName": "Done", + "isOrgProject": true + } + } + ] + } + ] + } + } + }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "taskName": "[Area Pod: Adam / David - PRs] David Assigned as Champion", + "actions": [ + { + "name": "removeFromProject", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "isOrgProject": true + } + }, + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "columnName": "Champion: David", + "isOrgProject": true + } + } + ], + "eventType": "pull_request", + "eventNames": [ + "pull_request" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isOpen", + "parameters": {} + }, + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Caching" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-FileSystem" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Console" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.Process" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Formats.Asn1" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Formats.Cbor" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO.Hashing" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Linq.Parallel" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Security" + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "isAssignedToUser", + "parameters": { + "user": "jozkee" + } + }, + { + "operator": "and", + "operands": [ + { + "name": "isAction", + "parameters": { + "action": "opened" + } + }, + { + "name": "isActivitySender", + "parameters": { + "user": "jozkee" + } + } + ] + } + ] + }, + { + "operator": "or", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "isOrgProject": true + } + } + ] + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "columnName": "Needs Champion", + "isOrgProject": true + } + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "columnName": "Done", + "isOrgProject": true + } + } + ] + } + ] + } + } + }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "taskName": "[Area Pod: Adam / David - PRs] Excluded", + "actions": [ + { + "name": "removeFromProject", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "isOrgProject": true + } + } + ], + "eventType": "pull_request", + "eventNames": [ + "pull_request" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "isOrgProject": true + } + }, + { + "operator": "not", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Adam / David - PRs", + "columnName": "Done", + "isOrgProject": true + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" + } + } + ] + } + ] + } + } + }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "taskName": "[Area Pod: Buyaa / Steve - Issue Triage] Moved to Another Area", + "actions": [ + { + "name": "removeFromProject", + "parameters": { + "projectName": "Area Pod: Buyaa / Steve - Issue Triage", + "isOrgProject": true + } + } + ], + "eventType": "issue", + "eventNames": [ + "issues" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-DependencyInjection" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Hosting" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.CodeDom" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ComponentModel" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ComponentModel.Composition" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Composition" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Configuration" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Reflection" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Reflection.Emit" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Reflection.Metadata" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Resources" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Text.RegularExpressions" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.DirectoryServices" + } + } + ] + } + ] + }, + { + "name": "isAction", + "parameters": { + "action": "unlabeled" + } + }, + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Buyaa / Steve - Issue Triage", + "isOrgProject": true + } + } + ] + } + } + }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "taskName": "[Area Pod: Buyaa / Steve - Issue Triage] Needs Triage", + "actions": [ + { + "name": "removeFromProject", + "parameters": { + "projectName": "Area Pod: Buyaa / Steve - Issue Triage", + "isOrgProject": true + } + }, + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Buyaa / Steve - Issue Triage", + "columnName": "Needs Triage", + "isOrgProject": true + } + } + ], + "eventType": "issue", + "eventNames": [ + "issues" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "operator": "and", + "operands": [ + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-DependencyInjection" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Hosting" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.CodeDom" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ComponentModel" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ComponentModel.Composition" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Composition" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Configuration" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Reflection" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Reflection.Emit" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Reflection.Metadata" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Resources" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Text.RegularExpressions" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.DirectoryServices" + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "isAction", + "parameters": { + "action": "reopened" + } + }, + { + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + } + ] + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "labelAdded", + "parameters": { + "label": "area-Extensions-DependencyInjection" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-Extensions-Hosting" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.CodeDom" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.ComponentModel" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.ComponentModel.Composition" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Composition" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Configuration" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Reflection" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Reflection.Emit" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Reflection.Metadata" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Resources" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Text.RegularExpressions" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.DirectoryServices" + } + } + ] + } + ] + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "operator": "or", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Buyaa / Steve - Issue Triage", + "isOrgProject": true + } + } + ] + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Buyaa / Steve - Issue Triage", + "isOrgProject": true, + "columnName": "Triaged" + } + } + ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + } + ] + }, + { + "operator": "not", "operands": [ { - "name": "isAction", + "name": "hasLabel", "parameters": { - "action": "opened" + "label": "os-tizen" } - }, + } + ] + }, + { + "operator": "not", + "operands": [ { - "name": "isActivitySender", + "name": "hasLabel", "parameters": { - "user": "adamsitnik" + "label": "os-tvos" } } ] - } - ] - }, - { - "operator": "or", - "operands": [ + }, { "operator": "not", "operands": [ { - "name": "isInProject", + "name": "hasLabel", "parameters": { - "projectName": "Area Pod: Adam / David - PRs", - "isOrgProject": true + "label": "arch-wasm" } } ] - }, - { - "name": "isInProjectColumn", - "parameters": { - "projectName": "Area Pod: Adam / David - PRs", - "columnName": "Needs Champion", - "isOrgProject": true - } - }, - { - "name": "isInProjectColumn", - "parameters": { - "projectName": "Area Pod: Adam / David - PRs", - "columnName": "Done", - "isOrgProject": true - } } ] } @@ -5314,131 +6694,132 @@ "taskSource": "fabricbot-config", "taskType": "trigger", "capabilityId": "IssueResponder", - "subCapability": "PullRequestResponder", + "subCapability": "IssueCommentResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Adam / David - PRs] David Assigned as Champion", + "taskName": "[Area Pod: Buyaa / Steve - Issue Triage] Needs Further Triage", "actions": [ { "name": "removeFromProject", "parameters": { - "projectName": "Area Pod: Adam / David - PRs", + "projectName": "Area Pod: Buyaa / Steve - Issue Triage", "isOrgProject": true } }, { "name": "addToProject", "parameters": { - "projectName": "Area Pod: Adam / David - PRs", - "columnName": "Champion: David", + "projectName": "Area Pod: Buyaa / Steve - Issue Triage", + "columnName": "Needs Triage", "isOrgProject": true } } ], - "eventType": "pull_request", + "eventType": "issue", "eventNames": [ - "pull_request" + "issue_comment" ], "conditions": { "operator": "and", "operands": [ - { - "name": "isOpen", - "parameters": {} - }, { "operator": "or", "operands": [ { "name": "hasLabel", "parameters": { - "label": "area-Extensions-Caching" + "label": "area-Extensions-DependencyInjection" } }, { "name": "hasLabel", "parameters": { - "label": "area-Extensions-FileSystem" + "label": "area-Extensions-Hosting" } }, { "name": "hasLabel", "parameters": { - "label": "area-System.Console" + "label": "area-System.CodeDom" } }, { "name": "hasLabel", "parameters": { - "label": "area-System.Diagnostics.Process" + "label": "area-System.ComponentModel" } }, { "name": "hasLabel", "parameters": { - "label": "area-System.Formats.Asn1" + "label": "area-System.ComponentModel.Composition" } }, { "name": "hasLabel", "parameters": { - "label": "area-System.Formats.Cbor" + "label": "area-System.Composition" } }, { "name": "hasLabel", "parameters": { - "label": "area-System.IO" + "label": "area-System.Configuration" } }, { "name": "hasLabel", "parameters": { - "label": "area-System.IO.Hashing" + "label": "area-System.Reflection" } }, { "name": "hasLabel", "parameters": { - "label": "area-System.Linq.Parallel" + "label": "area-System.Reflection.Emit" } }, { "name": "hasLabel", "parameters": { - "label": "area-System.Security" + "label": "area-System.Reflection.Metadata" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Resources" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Text.RegularExpressions" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "area-System.DirectoryServices" } } ] }, { - "operator": "or", + "operator": "not", "operands": [ { - "name": "isAssignedToUser", - "parameters": { - "user": "jozkee" - } - }, - { - "operator": "and", - "operands": [ - { - "name": "isAction", - "parameters": { - "action": "opened" - } - }, - { - "name": "isActivitySender", - "parameters": { - "user": "jozkee" - } - } - ] + "name": "isCloseAndComment", + "parameters": {} } ] }, + { + "name": "activitySenderHasPermissions", + "parameters": { + "permissions": "read" + } + }, { "operator": "or", "operands": [ @@ -5448,7 +6829,7 @@ { "name": "isInProject", "parameters": { - "projectName": "Area Pod: Adam / David - PRs", + "projectName": "Area Pod: Buyaa / Steve - Issue Triage", "isOrgProject": true } } @@ -5457,136 +6838,23 @@ { "name": "isInProjectColumn", "parameters": { - "projectName": "Area Pod: Adam / David - PRs", - "columnName": "Needs Champion", - "isOrgProject": true - } - }, - { - "name": "isInProjectColumn", - "parameters": { - "projectName": "Area Pod: Adam / David - PRs", - "columnName": "Done", + "projectName": "Area Pod: Buyaa / Steve - Issue Triage", + "columnName": "Triaged", "isOrgProject": true } - } - ] - } - ] - } - } - }, - { - "taskSource": "fabricbot-config", - "taskType": "trigger", - "capabilityId": "IssueResponder", - "subCapability": "IssuesOnlyResponder", - "version": "1.0", - "config": { - "taskName": "[Area Pod: Buyaa / Steve - Issue Triage] Moved to Another Area", - "actions": [ - { - "name": "removeFromProject", - "parameters": { - "projectName": "Area Pod: Buyaa / Steve - Issue Triage", - "isOrgProject": true - } - } - ], - "eventType": "issue", - "eventNames": [ - "issues" - ], - "conditions": { - "operator": "and", - "operands": [ - { - "operator": "and", - "operands": [ - { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "area-Extensions-DependencyInjection" - } - } - ] - }, - { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "area-Extensions-Hosting" - } - } - ] - }, - { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "area-System.CodeDom" - } - } - ] - }, - { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "area-System.ComponentModel" - } - } - ] - }, - { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "area-System.ComponentModel.Composition" - } - } - ] - }, - { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Composition" - } - } - ] - }, - { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Configuration" - } - } - ] - }, + } + ] + }, + { + "operator": "and", + "operands": [ { "operator": "not", "operands": [ { "name": "hasLabel", "parameters": { - "label": "area-System.Reflection" + "label": "os-android" } } ] @@ -5597,7 +6865,7 @@ { "name": "hasLabel", "parameters": { - "label": "area-System.Reflection.Emit" + "label": "os-maccatalyst" } } ] @@ -5608,7 +6876,7 @@ { "name": "hasLabel", "parameters": { - "label": "area-System.Reflection.Metadata" + "label": "os-ios" } } ] @@ -5619,7 +6887,7 @@ { "name": "hasLabel", "parameters": { - "label": "area-System.Resources" + "label": "os-tizen" } } ] @@ -5630,7 +6898,7 @@ { "name": "hasLabel", "parameters": { - "label": "area-System.Text.RegularExpressions" + "label": "os-tvos" } } ] @@ -5641,25 +6909,12 @@ { "name": "hasLabel", "parameters": { - "label": "area-System.DirectoryServices" + "label": "arch-wasm" } } ] } ] - }, - { - "name": "isAction", - "parameters": { - "action": "unlabeled" - } - }, - { - "name": "isInProject", - "parameters": { - "projectName": "Area Pod: Buyaa / Steve - Issue Triage", - "isOrgProject": true - } } ] } @@ -5672,21 +6927,20 @@ "subCapability": "IssuesOnlyResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Buyaa / Steve - Issue Triage] Needs Triage", + "taskName": "[Area Pod: Buyaa / Steve - Issue Triage] Triaged", "actions": [ { - "name": "removeFromProject", + "name": "addToProject", "parameters": { "projectName": "Area Pod: Buyaa / Steve - Issue Triage", + "columnName": "Triaged", "isOrgProject": true } }, { - "name": "addToProject", + "name": "removeLabel", "parameters": { - "projectName": "Area Pod: Buyaa / Steve - Issue Triage", - "columnName": "Needs Triage", - "isOrgProject": true + "label": "untriaged" } } ], @@ -5697,228 +6951,120 @@ "conditions": { "operator": "and", "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Buyaa / Steve - Issue Triage", + "isOrgProject": true + } + }, { "operator": "or", "operands": [ { - "operator": "and", - "operands": [ - { - "operator": "or", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "area-Extensions-DependencyInjection" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-Extensions-Hosting" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.CodeDom" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.ComponentModel" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.ComponentModel.Composition" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Composition" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Configuration" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Reflection" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Reflection.Emit" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Reflection.Metadata" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Resources" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Text.RegularExpressions" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.DirectoryServices" - } - } - ] - }, - { - "operator": "or", - "operands": [ - { - "name": "isAction", - "parameters": { - "action": "reopened" - } - }, - { - "operator": "not", - "operands": [ - { - "name": "isInMilestone", - "parameters": {} - } - ] - } - ] - } - ] + "name": "addedToMilestone", + "parameters": {} }, { - "operator": "or", - "operands": [ - { - "name": "labelAdded", - "parameters": { - "label": "area-Extensions-DependencyInjection" - } - }, - { - "name": "labelAdded", - "parameters": { - "label": "area-Extensions-Hosting" - } - }, - { - "name": "labelAdded", - "parameters": { - "label": "area-System.CodeDom" - } - }, - { - "name": "labelAdded", - "parameters": { - "label": "area-System.ComponentModel" - } - }, - { - "name": "labelAdded", - "parameters": { - "label": "area-System.ComponentModel.Composition" - } - }, - { - "name": "labelAdded", - "parameters": { - "label": "area-System.Composition" - } - }, - { - "name": "labelAdded", - "parameters": { - "label": "area-System.Configuration" - } - }, - { - "name": "labelAdded", - "parameters": { - "label": "area-System.Reflection" - } - }, - { - "name": "labelAdded", - "parameters": { - "label": "area-System.Reflection.Emit" - } - }, - { - "name": "labelAdded", - "parameters": { - "label": "area-System.Reflection.Metadata" - } - }, - { - "name": "labelAdded", - "parameters": { - "label": "area-System.Resources" - } - }, - { - "name": "labelAdded", - "parameters": { - "label": "area-System.Text.RegularExpressions" - } - }, - { - "name": "labelAdded", - "parameters": { - "label": "area-System.DirectoryServices" - } - } - ] + "name": "labelAdded", + "parameters": { + "label": "needs-author-action" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "api-ready-for-review" + } + }, + { + "name": "isAction", + "parameters": { + "action": "closed" + } } ] + } + ] + } + } + }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "taskName": "[Area Pod: Buyaa / Steve - Issue Triage] Buyaa Updated Issue", + "actions": [ + { + "name": "moveToProjectColumn", + "parameters": { + "projectName": "Area Pod: Buyaa / Steve - Issue Triage", + "columnName": "Triage: Buyaa", + "isOrgProject": true + } + } + ], + "eventType": "issue", + "eventNames": [ + "issues" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Buyaa / Steve - Issue Triage", + "isOrgProject": true, + "columnName": "Needs Triage" + } }, { - "name": "isOpen", - "parameters": {} + "name": "isActivitySender", + "parameters": { + "user": "buyaa-n" + } }, { - "operator": "or", + "operator": "and", "operands": [ + { + "name": "isOpen", + "parameters": {} + }, { "operator": "not", "operands": [ { - "name": "isInProject", + "name": "isInMilestone", + "parameters": {} + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", "parameters": { - "projectName": "Area Pod: Buyaa / Steve - Issue Triage", - "isOrgProject": true + "label": "needs-author-action" } } ] }, { - "name": "isInProjectColumn", - "parameters": { - "projectName": "Area Pod: Buyaa / Steve - Issue Triage", - "isOrgProject": true, - "columnName": "Triaged" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] } ] } @@ -5933,20 +7079,13 @@ "subCapability": "IssueCommentResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Buyaa / Steve - Issue Triage] Needs Further Triage", + "taskName": "[Area Pod: Buyaa / Steve - Issue Triage] Buyaa Commented", "actions": [ { - "name": "removeFromProject", - "parameters": { - "projectName": "Area Pod: Buyaa / Steve - Issue Triage", - "isOrgProject": true - } - }, - { - "name": "addToProject", + "name": "moveToProjectColumn", "parameters": { "projectName": "Area Pod: Buyaa / Steve - Issue Triage", - "columnName": "Needs Triage", + "columnName": "Triage: Buyaa", "isOrgProject": true } } @@ -5959,125 +7098,56 @@ "operator": "and", "operands": [ { - "operator": "or", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "area-Extensions-DependencyInjection" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-Extensions-Hosting" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.CodeDom" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.ComponentModel" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.ComponentModel.Composition" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Composition" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Configuration" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Reflection" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Reflection.Emit" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Reflection.Metadata" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Resources" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.Text.RegularExpressions" - } - }, - { - "name": "hasLabel", - "parameters": { - "label": "area-System.DirectoryServices" - } - } - ] - }, - { - "operator": "not", - "operands": [ - { - "name": "isCloseAndComment", - "parameters": {} - } - ] + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Buyaa / Steve - Issue Triage", + "isOrgProject": true, + "columnName": "Needs Triage" + } }, { - "name": "activitySenderHasPermissions", + "name": "isActivitySender", "parameters": { - "permissions": "read" + "user": "buyaa-n" } }, { - "operator": "or", + "operator": "and", "operands": [ + { + "name": "isOpen", + "parameters": {} + }, { "operator": "not", "operands": [ { - "name": "isInProject", + "name": "isInMilestone", + "parameters": {} + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", "parameters": { - "projectName": "Area Pod: Buyaa / Steve - Issue Triage", - "isOrgProject": true + "label": "needs-author-action" } } ] }, { - "name": "isInProjectColumn", - "parameters": { - "projectName": "Area Pod: Buyaa / Steve - Issue Triage", - "columnName": "Triaged", - "isOrgProject": true - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] } ] } @@ -6092,21 +7162,15 @@ "subCapability": "IssuesOnlyResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Buyaa / Steve - Issue Triage] Triaged", + "taskName": "[Area Pod: Buyaa / Steve - Issue Triage] Steve H Updated Issue", "actions": [ { - "name": "addToProject", + "name": "moveToProjectColumn", "parameters": { "projectName": "Area Pod: Buyaa / Steve - Issue Triage", - "columnName": "Triaged", + "columnName": "Triage: Steve H", "isOrgProject": true } - }, - { - "name": "removeLabel", - "parameters": { - "label": "untriaged" - } } ], "eventType": "issue", @@ -6117,36 +7181,56 @@ "operator": "and", "operands": [ { - "name": "isInProject", + "name": "isInProjectColumn", "parameters": { "projectName": "Area Pod: Buyaa / Steve - Issue Triage", - "isOrgProject": true + "isOrgProject": true, + "columnName": "Needs Triage" } }, { - "operator": "or", + "name": "isActivitySender", + "parameters": { + "user": "steveharter" + } + }, + { + "operator": "and", "operands": [ { - "name": "addedToMilestone", + "name": "isOpen", "parameters": {} }, { - "name": "labelAdded", - "parameters": { - "label": "needs-author-action" - } + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] }, { - "name": "labelAdded", - "parameters": { - "label": "api-ready-for-review" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] }, { - "name": "isAction", - "parameters": { - "action": "closed" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] } ] } @@ -6158,23 +7242,23 @@ "taskSource": "fabricbot-config", "taskType": "trigger", "capabilityId": "IssueResponder", - "subCapability": "IssuesOnlyResponder", + "subCapability": "IssueCommentResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Buyaa / Steve - Issue Triage] Buyaa Updated Issue", + "taskName": "[Area Pod: Buyaa / Steve - Issue Triage] Steve H Commented", "actions": [ { "name": "moveToProjectColumn", "parameters": { "projectName": "Area Pod: Buyaa / Steve - Issue Triage", - "columnName": "Triage: Buyaa", + "columnName": "Triage: Steve H", "isOrgProject": true } } ], "eventType": "issue", "eventNames": [ - "issues" + "issue_comment" ], "conditions": { "operator": "and", @@ -6190,41 +7274,46 @@ { "name": "isActivitySender", "parameters": { - "user": "buyaa-n" + "user": "steveharter" } }, { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "and", "operands": [ { - "name": "isInMilestone", + "name": "isOpen", "parameters": {} - } - ] - }, - { - "operator": "not", - "operands": [ + }, { - "name": "hasLabel", - "parameters": { - "label": "needs-author-action" - } - } - ] - }, - { - "operator": "not", - "operands": [ + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + }, { - "name": "hasLabel", - "parameters": { - "label": "api-ready-for-review" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] } ] } @@ -6236,72 +7325,70 @@ "taskSource": "fabricbot-config", "taskType": "trigger", "capabilityId": "IssueResponder", - "subCapability": "IssueCommentResponder", + "subCapability": "IssuesOnlyResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Buyaa / Steve - Issue Triage] Buyaa Commented", + "taskName": "[Area Pod: Buyaa / Steve - Issue Triage] Excluded", "actions": [ { - "name": "moveToProjectColumn", + "name": "removeFromProject", "parameters": { "projectName": "Area Pod: Buyaa / Steve - Issue Triage", - "columnName": "Triage: Buyaa", "isOrgProject": true } } ], "eventType": "issue", "eventNames": [ - "issue_comment" + "issues" ], "conditions": { "operator": "and", "operands": [ { - "name": "isInProjectColumn", + "name": "isInProject", "parameters": { "projectName": "Area Pod: Buyaa / Steve - Issue Triage", - "isOrgProject": true, - "columnName": "Needs Triage" - } - }, - { - "name": "isActivitySender", - "parameters": { - "user": "buyaa-n" + "isOrgProject": true } }, { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "or", "operands": [ { - "name": "isInMilestone", - "parameters": {} - } - ] - }, - { - "operator": "not", - "operands": [ + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + }, { "name": "hasLabel", "parameters": { - "label": "needs-author-action" + "label": "os-maccatalyst" } - } - ] - }, - { - "operator": "not", - "operands": [ + }, { "name": "hasLabel", "parameters": { - "label": "api-ready-for-review" + "label": "os-ios" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" } } ] @@ -6317,150 +7404,183 @@ "subCapability": "IssuesOnlyResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Buyaa / Steve - Issue Triage] Steve H Updated Issue", + "taskName": "[Area Pod: Buyaa / Steve - PRs] Moved to Another Area", "actions": [ { - "name": "moveToProjectColumn", + "name": "removeFromProject", "parameters": { - "projectName": "Area Pod: Buyaa / Steve - Issue Triage", - "columnName": "Triage: Steve H", + "projectName": "Area Pod: Buyaa / Steve - PRs", "isOrgProject": true } } ], - "eventType": "issue", + "eventType": "pull_request", "eventNames": [ - "issues" + "pull_request" ], "conditions": { "operator": "and", "operands": [ { - "name": "isInProjectColumn", - "parameters": { - "projectName": "Area Pod: Buyaa / Steve - Issue Triage", - "isOrgProject": true, - "columnName": "Needs Triage" - } - }, - { - "name": "isActivitySender", - "parameters": { - "user": "steveharter" - } - }, - { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "and", "operands": [ { - "name": "isInMilestone", - "parameters": {} - } - ] - }, - { - "operator": "not", - "operands": [ + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-DependencyInjection" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Extensions-Hosting" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.CodeDom" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ComponentModel" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ComponentModel.Composition" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Composition" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Configuration" + } + } + ] + }, { - "name": "hasLabel", - "parameters": { - "label": "needs-author-action" - } - } - ] - }, - { - "operator": "not", - "operands": [ + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Reflection" + } + } + ] + }, { - "name": "hasLabel", - "parameters": { - "label": "api-ready-for-review" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Reflection.Emit" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Reflection.Metadata" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Resources" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Text.RegularExpressions" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.DirectoryServices" + } + } + ] } ] - } - ] - } - } - }, - { - "taskSource": "fabricbot-config", - "taskType": "trigger", - "capabilityId": "IssueResponder", - "subCapability": "IssueCommentResponder", - "version": "1.0", - "config": { - "taskName": "[Area Pod: Buyaa / Steve - Issue Triage] Steve H Commented", - "actions": [ - { - "name": "moveToProjectColumn", - "parameters": { - "projectName": "Area Pod: Buyaa / Steve - Issue Triage", - "columnName": "Triage: Steve H", - "isOrgProject": true - } - } - ], - "eventType": "issue", - "eventNames": [ - "issue_comment" - ], - "conditions": { - "operator": "and", - "operands": [ + }, { - "name": "isInProjectColumn", + "name": "isAction", "parameters": { - "projectName": "Area Pod: Buyaa / Steve - Issue Triage", - "isOrgProject": true, - "columnName": "Needs Triage" + "action": "unlabeled" } }, { - "name": "isActivitySender", + "name": "isInProject", "parameters": { - "user": "steveharter" + "projectName": "Area Pod: Buyaa / Steve - PRs", + "isOrgProject": true } - }, - { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", - "operands": [ - { - "name": "isInMilestone", - "parameters": {} - } - ] - }, - { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "needs-author-action" - } - } - ] - }, - { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "api-ready-for-review" - } - } - ] } ] } @@ -6848,21 +7968,92 @@ "operator": "not", "operands": [ { - "name": "isInProject", + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Buyaa / Steve - PRs", + "isOrgProject": true + } + } + ] + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Buyaa / Steve - PRs", + "columnName": "Done", + "isOrgProject": true + } + } + ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", "parameters": { - "projectName": "Area Pod: Buyaa / Steve - PRs", - "isOrgProject": true + "label": "arch-wasm" } } ] - }, - { - "name": "isInProjectColumn", - "parameters": { - "projectName": "Area Pod: Buyaa / Steve - PRs", - "columnName": "Done", - "isOrgProject": true - } } ] } @@ -7046,6 +8237,77 @@ } } ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" + } + } + ] + } + ] } ] } @@ -7419,6 +8681,95 @@ } } }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "taskName": "[Area Pod: Buyaa / Steve - PRs] Excluded", + "actions": [ + { + "name": "removeFromProject", + "parameters": { + "projectName": "Area Pod: Buyaa / Steve - PRs", + "isOrgProject": true + } + } + ], + "eventType": "pull_request", + "eventNames": [ + "pull_request" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Buyaa / Steve - PRs", + "isOrgProject": true + } + }, + { + "operator": "not", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Buyaa / Steve - PRs", + "columnName": "Done", + "isOrgProject": true + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" + } + } + ] + } + ] + } + } + }, { "taskSource": "fabricbot-config", "taskType": "trigger", @@ -7775,47 +9126,118 @@ } }, { - "name": "labelAdded", + "name": "labelAdded", + "parameters": { + "label": "area-System.Management" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.ServiceProcess" + } + } + ] + } + ] + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "operator": "or", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Carlos / Viktor - Issue Triage", + "isOrgProject": true + } + } + ] + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Carlos / Viktor - Issue Triage", + "isOrgProject": true, + "columnName": "Triaged" + } + } + ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", "parameters": { - "label": "area-System.Management" + "label": "os-tizen" } - }, + } + ] + }, + { + "operator": "not", + "operands": [ { - "name": "labelAdded", + "name": "hasLabel", "parameters": { - "label": "area-System.ServiceProcess" + "label": "os-tvos" } } ] - } - ] - }, - { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "or", - "operands": [ + }, { "operator": "not", "operands": [ { - "name": "isInProject", + "name": "hasLabel", "parameters": { - "projectName": "Area Pod: Carlos / Viktor - Issue Triage", - "isOrgProject": true + "label": "arch-wasm" } } ] - }, - { - "name": "isInProjectColumn", - "parameters": { - "projectName": "Area Pod: Carlos / Viktor - Issue Triage", - "isOrgProject": true, - "columnName": "Triaged" - } } ] } @@ -7965,6 +9387,77 @@ } } ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" + } + } + ] + } + ] } ] } @@ -7996,42 +9489,208 @@ ], "eventType": "issue", "eventNames": [ - "issues" + "issues" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Carlos / Viktor - Issue Triage", + "isOrgProject": true + } + }, + { + "operator": "or", + "operands": [ + { + "name": "addedToMilestone", + "parameters": {} + }, + { + "name": "labelAdded", + "parameters": { + "label": "needs-author-action" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "api-ready-for-review" + } + }, + { + "name": "isAction", + "parameters": { + "action": "closed" + } + } + ] + } + ] + } + } + }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "taskName": "[Area Pod: Carlos / Viktor - Issue Triage] Carlos Updated Issue", + "actions": [ + { + "name": "moveToProjectColumn", + "parameters": { + "projectName": "Area Pod: Carlos / Viktor - Issue Triage", + "columnName": "Triage: Carlos", + "isOrgProject": true + } + } + ], + "eventType": "issue", + "eventNames": [ + "issues" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Carlos / Viktor - Issue Triage", + "isOrgProject": true, + "columnName": "Needs Triage" + } + }, + { + "name": "isActivitySender", + "parameters": { + "user": "carlossanlop" + } + }, + { + "operator": "and", + "operands": [ + { + "name": "isOpen", + "parameters": {} + }, + { + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] + } + ] + } + ] + } + } + }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssueCommentResponder", + "version": "1.0", + "config": { + "taskName": "[Area Pod: Carlos / Viktor - Issue Triage] Carlos Commented", + "actions": [ + { + "name": "moveToProjectColumn", + "parameters": { + "projectName": "Area Pod: Carlos / Viktor - Issue Triage", + "columnName": "Triage: Carlos", + "isOrgProject": true + } + } + ], + "eventType": "issue", + "eventNames": [ + "issue_comment" ], "conditions": { "operator": "and", "operands": [ { - "name": "isInProject", + "name": "isInProjectColumn", "parameters": { "projectName": "Area Pod: Carlos / Viktor - Issue Triage", - "isOrgProject": true + "isOrgProject": true, + "columnName": "Needs Triage" } }, { - "operator": "or", + "name": "isActivitySender", + "parameters": { + "user": "carlossanlop" + } + }, + { + "operator": "and", "operands": [ { - "name": "addedToMilestone", + "name": "isOpen", "parameters": {} }, { - "name": "labelAdded", - "parameters": { - "label": "needs-author-action" - } + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] }, { - "name": "labelAdded", - "parameters": { - "label": "api-ready-for-review" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] }, { - "name": "isAction", - "parameters": { - "action": "closed" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] } ] } @@ -8046,13 +9705,13 @@ "subCapability": "IssuesOnlyResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Carlos / Viktor - Issue Triage] Carlos Updated Issue", + "taskName": "[Area Pod: Carlos / Viktor - Issue Triage] Viktor Updated Issue", "actions": [ { "name": "moveToProjectColumn", "parameters": { "projectName": "Area Pod: Carlos / Viktor - Issue Triage", - "columnName": "Triage: Carlos", + "columnName": "Triage: Viktor", "isOrgProject": true } } @@ -8075,41 +9734,46 @@ { "name": "isActivitySender", "parameters": { - "user": "carlossanlop" + "user": "viktorhofer" } }, { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "and", "operands": [ { - "name": "isInMilestone", + "name": "isOpen", "parameters": {} - } - ] - }, - { - "operator": "not", - "operands": [ + }, { - "name": "hasLabel", - "parameters": { - "label": "needs-author-action" - } - } - ] - }, - { - "operator": "not", - "operands": [ + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + }, { - "name": "hasLabel", - "parameters": { - "label": "api-ready-for-review" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] } ] } @@ -8124,13 +9788,13 @@ "subCapability": "IssueCommentResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Carlos / Viktor - Issue Triage] Carlos Commented", + "taskName": "[Area Pod: Carlos / Viktor - Issue Triage] Viktor Commented", "actions": [ { "name": "moveToProjectColumn", "parameters": { "projectName": "Area Pod: Carlos / Viktor - Issue Triage", - "columnName": "Triage: Carlos", + "columnName": "Triage: Viktor", "isOrgProject": true } } @@ -8153,41 +9817,46 @@ { "name": "isActivitySender", "parameters": { - "user": "carlossanlop" + "user": "viktorhofer" } }, { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "and", "operands": [ { - "name": "isInMilestone", + "name": "isOpen", "parameters": {} - } - ] - }, - { - "operator": "not", - "operands": [ + }, { - "name": "hasLabel", - "parameters": { - "label": "needs-author-action" - } - } - ] - }, - { - "operator": "not", - "operands": [ + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + }, { - "name": "hasLabel", - "parameters": { - "label": "api-ready-for-review" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] } ] } @@ -8202,13 +9871,12 @@ "subCapability": "IssuesOnlyResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Carlos / Viktor - Issue Triage] Viktor Updated Issue", + "taskName": "[Area Pod: Carlos / Viktor - Issue Triage] Excluded", "actions": [ { - "name": "moveToProjectColumn", + "name": "removeFromProject", "parameters": { "projectName": "Area Pod: Carlos / Viktor - Issue Triage", - "columnName": "Triage: Viktor", "isOrgProject": true } } @@ -8221,50 +9889,49 @@ "operator": "and", "operands": [ { - "name": "isInProjectColumn", + "name": "isInProject", "parameters": { "projectName": "Area Pod: Carlos / Viktor - Issue Triage", - "isOrgProject": true, - "columnName": "Needs Triage" - } - }, - { - "name": "isActivitySender", - "parameters": { - "user": "viktorhofer" + "isOrgProject": true } }, { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "or", "operands": [ { - "name": "isInMilestone", - "parameters": {} - } - ] - }, - { - "operator": "not", - "operands": [ + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + }, { "name": "hasLabel", "parameters": { - "label": "needs-author-action" + "label": "os-maccatalyst" } - } - ] - }, - { - "operator": "not", - "operands": [ + }, { "name": "hasLabel", "parameters": { - "label": "api-ready-for-review" + "label": "os-ios" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" } } ] @@ -8277,75 +9944,164 @@ "taskSource": "fabricbot-config", "taskType": "trigger", "capabilityId": "IssueResponder", - "subCapability": "IssueCommentResponder", + "subCapability": "IssuesOnlyResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Carlos / Viktor - Issue Triage] Viktor Commented", + "taskName": "[Area Pod: Carlos / Viktor - PRs] Moved to Another Area", "actions": [ { - "name": "moveToProjectColumn", + "name": "removeFromProject", "parameters": { - "projectName": "Area Pod: Carlos / Viktor - Issue Triage", - "columnName": "Triage: Viktor", + "projectName": "Area Pod: Carlos / Viktor - PRs", "isOrgProject": true } } ], - "eventType": "issue", + "eventType": "pull_request", "eventNames": [ - "issue_comment" + "pull_request" ], "conditions": { "operator": "and", "operands": [ { - "name": "isInProjectColumn", - "parameters": { - "projectName": "Area Pod: Carlos / Viktor - Issue Triage", - "isOrgProject": true, - "columnName": "Needs Triage" - } - }, - { - "name": "isActivitySender", - "parameters": { - "user": "viktorhofer" - } - }, - { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "and", "operands": [ { - "name": "isInMilestone", - "parameters": {} + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-DependencyModel" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Infrastructure-libraries" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Microsoft.Win32" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.EventLog" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.PerformanceCounter" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Diagnostics.TraceSource" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Drawing" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Formats.Tar" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.IO.Compression" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Management" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.ServiceProcess" + } + } + ] } ] }, { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "needs-author-action" - } - } - ] + "name": "isAction", + "parameters": { + "action": "unlabeled" + } }, { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "api-ready-for-review" - } - } - ] + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Carlos / Viktor - PRs", + "isOrgProject": true + } } ] } @@ -8659,22 +10415,107 @@ "operator": "not", "operands": [ { - "name": "isActivitySender", + "name": "isActivitySender", + "parameters": { + "user": "carlossanlop" + } + } + ] + } + ], + [ + { + "operator": "not", + "operands": [ + { + "name": "isAssignedToUser", + "parameters": { + "user": "viktorhofer" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "isActivitySender", + "parameters": { + "user": "viktorhofer" + } + } + ] + } + ] + ], + { + "operator": "or", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Carlos / Viktor - PRs", + "isOrgProject": true + } + } + ] + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Carlos / Viktor - PRs", + "columnName": "Done", + "isOrgProject": true + } + } + ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", "parameters": { - "user": "carlossanlop" + "label": "os-ios" } } ] - } - ], - [ + }, { "operator": "not", "operands": [ { - "name": "isAssignedToUser", + "name": "hasLabel", "parameters": { - "user": "viktorhofer" + "label": "os-tizen" } } ] @@ -8683,37 +10524,23 @@ "operator": "not", "operands": [ { - "name": "isActivitySender", + "name": "hasLabel", "parameters": { - "user": "viktorhofer" + "label": "os-tvos" } } ] - } - ] - ], - { - "operator": "or", - "operands": [ + }, { "operator": "not", "operands": [ { - "name": "isInProject", + "name": "hasLabel", "parameters": { - "projectName": "Area Pod: Carlos / Viktor - PRs", - "isOrgProject": true + "label": "arch-wasm" } } ] - }, - { - "name": "isInProjectColumn", - "parameters": { - "projectName": "Area Pod: Carlos / Viktor - PRs", - "columnName": "Done", - "isOrgProject": true - } } ] } @@ -8885,6 +10712,77 @@ } } ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" + } + } + ] + } + ] } ] } @@ -9234,6 +11132,95 @@ } } }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "taskName": "[Area Pod: Carlos / Viktor - PRs] Excluded", + "actions": [ + { + "name": "removeFromProject", + "parameters": { + "projectName": "Area Pod: Carlos / Viktor - PRs", + "isOrgProject": true + } + } + ], + "eventType": "pull_request", + "eventNames": [ + "pull_request" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Carlos / Viktor - PRs", + "isOrgProject": true + } + }, + { + "operator": "not", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Carlos / Viktor - PRs", + "columnName": "Done", + "isOrgProject": true + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" + } + } + ] + } + ] + } + } + }, { "taskSource": "fabricbot-config", "taskType": "trigger", @@ -9544,47 +11531,107 @@ } }, { - "name": "labelAdded", + "name": "labelAdded", + "parameters": { + "label": "area-System.Threading.Channels" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "area-System.Threading.Tasks" + } + } + ] + } + ] + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "operator": "or", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Michael / Tanner - Issue Triage", + "isOrgProject": true + } + } + ] + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Michael / Tanner - Issue Triage", + "isOrgProject": true, + "columnName": "Triaged" + } + } + ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", "parameters": { - "label": "area-System.Threading.Channels" + "label": "os-maccatalyst" } - }, + } + ] + }, + { + "operator": "not", + "operands": [ { - "name": "labelAdded", + "name": "hasLabel", "parameters": { - "label": "area-System.Threading.Tasks" + "label": "os-ios" } } ] - } - ] - }, - { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "or", - "operands": [ + }, { "operator": "not", "operands": [ { - "name": "isInProject", + "name": "hasLabel", "parameters": { - "projectName": "Area Pod: Michael / Tanner - Issue Triage", - "isOrgProject": true + "label": "os-tizen" } } ] }, { - "name": "isInProjectColumn", - "parameters": { - "projectName": "Area Pod: Michael / Tanner - Issue Triage", - "isOrgProject": true, - "columnName": "Triaged" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + } + ] } ] } @@ -9722,6 +11769,218 @@ } } ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + } + ] + } + ] + } + ] + } + } + }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "taskName": "[Area Pod: Michael / Tanner - Issue Triage] Triaged", + "actions": [ + { + "name": "addToProject", + "parameters": { + "projectName": "Area Pod: Michael / Tanner - Issue Triage", + "columnName": "Triaged", + "isOrgProject": true + } + }, + { + "name": "removeLabel", + "parameters": { + "label": "untriaged" + } + } + ], + "eventType": "issue", + "eventNames": [ + "issues" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Michael / Tanner - Issue Triage", + "isOrgProject": true + } + }, + { + "operator": "or", + "operands": [ + { + "name": "addedToMilestone", + "parameters": {} + }, + { + "name": "labelAdded", + "parameters": { + "label": "needs-author-action" + } + }, + { + "name": "labelAdded", + "parameters": { + "label": "api-ready-for-review" + } + }, + { + "name": "isAction", + "parameters": { + "action": "closed" + } + } + ] + } + ] + } + } + }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "taskName": "[Area Pod: Michael / Tanner - Issue Triage] Michael Updated Issue", + "actions": [ + { + "name": "moveToProjectColumn", + "parameters": { + "projectName": "Area Pod: Michael / Tanner - Issue Triage", + "columnName": "Triage: Michael", + "isOrgProject": true + } + } + ], + "eventType": "issue", + "eventNames": [ + "issues" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Michael / Tanner - Issue Triage", + "isOrgProject": true, + "columnName": "Needs Triage" + } + }, + { + "name": "isActivitySender", + "parameters": { + "user": "michaelgsharp" + } + }, + { + "operator": "and", + "operands": [ + { + "name": "isOpen", + "parameters": {} + }, + { + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] + } + ] } ] } @@ -9731,64 +11990,78 @@ "taskSource": "fabricbot-config", "taskType": "trigger", "capabilityId": "IssueResponder", - "subCapability": "IssuesOnlyResponder", + "subCapability": "IssueCommentResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Michael / Tanner - Issue Triage] Triaged", + "taskName": "[Area Pod: Michael / Tanner - Issue Triage] Michael Commented", "actions": [ { - "name": "addToProject", + "name": "moveToProjectColumn", "parameters": { "projectName": "Area Pod: Michael / Tanner - Issue Triage", - "columnName": "Triaged", + "columnName": "Triage: Michael", "isOrgProject": true } - }, - { - "name": "removeLabel", - "parameters": { - "label": "untriaged" - } } ], "eventType": "issue", "eventNames": [ - "issues" + "issue_comment" ], "conditions": { "operator": "and", "operands": [ { - "name": "isInProject", + "name": "isInProjectColumn", "parameters": { "projectName": "Area Pod: Michael / Tanner - Issue Triage", - "isOrgProject": true + "isOrgProject": true, + "columnName": "Needs Triage" } }, { - "operator": "or", + "name": "isActivitySender", + "parameters": { + "user": "michaelgsharp" + } + }, + { + "operator": "and", "operands": [ { - "name": "addedToMilestone", + "name": "isOpen", "parameters": {} }, { - "name": "labelAdded", - "parameters": { - "label": "needs-author-action" - } + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] }, { - "name": "labelAdded", - "parameters": { - "label": "api-ready-for-review" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] }, { - "name": "isAction", - "parameters": { - "action": "closed" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] } ] } @@ -9803,13 +12076,13 @@ "subCapability": "IssuesOnlyResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Michael / Tanner - Issue Triage] Michael Updated Issue", + "taskName": "[Area Pod: Michael / Tanner - Issue Triage] Tanner Updated Issue", "actions": [ { "name": "moveToProjectColumn", "parameters": { "projectName": "Area Pod: Michael / Tanner - Issue Triage", - "columnName": "Triage: Michael", + "columnName": "Triage: Tanner", "isOrgProject": true } } @@ -9832,41 +12105,46 @@ { "name": "isActivitySender", "parameters": { - "user": "michaelgsharp" + "user": "tannergooding" } }, { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "and", "operands": [ { - "name": "isInMilestone", + "name": "isOpen", "parameters": {} - } - ] - }, - { - "operator": "not", - "operands": [ + }, { - "name": "hasLabel", - "parameters": { - "label": "needs-author-action" - } - } - ] - }, - { - "operator": "not", - "operands": [ + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + }, { - "name": "hasLabel", - "parameters": { - "label": "api-ready-for-review" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] } ] } @@ -9881,13 +12159,13 @@ "subCapability": "IssueCommentResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Michael / Tanner - Issue Triage] Michael Commented", + "taskName": "[Area Pod: Michael / Tanner - Issue Triage] Tanner Commented", "actions": [ { "name": "moveToProjectColumn", "parameters": { "projectName": "Area Pod: Michael / Tanner - Issue Triage", - "columnName": "Triage: Michael", + "columnName": "Triage: Tanner", "isOrgProject": true } } @@ -9910,41 +12188,46 @@ { "name": "isActivitySender", "parameters": { - "user": "michaelgsharp" + "user": "tannergooding" } }, { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "and", "operands": [ { - "name": "isInMilestone", + "name": "isOpen", "parameters": {} - } - ] - }, - { - "operator": "not", - "operands": [ + }, { - "name": "hasLabel", - "parameters": { - "label": "needs-author-action" - } - } - ] - }, - { - "operator": "not", - "operands": [ + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + }, { - "name": "hasLabel", - "parameters": { - "label": "api-ready-for-review" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] } ] } @@ -9959,13 +12242,12 @@ "subCapability": "IssuesOnlyResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Michael / Tanner - Issue Triage] Tanner Updated Issue", + "taskName": "[Area Pod: Michael / Tanner - Issue Triage] Excluded", "actions": [ { - "name": "moveToProjectColumn", + "name": "removeFromProject", "parameters": { "projectName": "Area Pod: Michael / Tanner - Issue Triage", - "columnName": "Triage: Tanner", "isOrgProject": true } } @@ -9978,50 +12260,43 @@ "operator": "and", "operands": [ { - "name": "isInProjectColumn", + "name": "isInProject", "parameters": { "projectName": "Area Pod: Michael / Tanner - Issue Triage", - "isOrgProject": true, - "columnName": "Needs Triage" - } - }, - { - "name": "isActivitySender", - "parameters": { - "user": "tannergooding" + "isOrgProject": true } }, { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "or", "operands": [ { - "name": "isInMilestone", - "parameters": {} - } - ] - }, - { - "operator": "not", - "operands": [ + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + }, { "name": "hasLabel", "parameters": { - "label": "needs-author-action" + "label": "os-maccatalyst" } - } - ] - }, - { - "operator": "not", - "operands": [ + }, { "name": "hasLabel", "parameters": { - "label": "api-ready-for-review" + "label": "os-ios" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" } } ] @@ -10034,75 +12309,142 @@ "taskSource": "fabricbot-config", "taskType": "trigger", "capabilityId": "IssueResponder", - "subCapability": "IssueCommentResponder", + "subCapability": "IssuesOnlyResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Michael / Tanner - Issue Triage] Tanner Commented", + "taskName": "[Area Pod: Michael / Tanner - PRs] Moved to Another Area", "actions": [ { - "name": "moveToProjectColumn", + "name": "removeFromProject", "parameters": { - "projectName": "Area Pod: Michael / Tanner - Issue Triage", - "columnName": "Triage: Tanner", + "projectName": "Area Pod: Michael / Tanner - PRs", "isOrgProject": true } } ], - "eventType": "issue", + "eventType": "pull_request", "eventNames": [ - "issue_comment" + "pull_request" ], "conditions": { "operator": "and", "operands": [ { - "name": "isInProjectColumn", - "parameters": { - "projectName": "Area Pod: Michael / Tanner - Issue Triage", - "isOrgProject": true, - "columnName": "Needs Triage" - } - }, - { - "name": "isActivitySender", - "parameters": { - "user": "tannergooding" - } - }, - { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "and", "operands": [ { - "name": "isInMilestone", - "parameters": {} + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Buffers" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Memory" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Numerics" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Numerics.Tensors" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Runtime" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Runtime.CompilerServices" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Runtime.Intrinsics" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Threading.Channels" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-System.Threading.Tasks" + } + } + ] } ] }, { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "needs-author-action" - } - } - ] + "name": "isAction", + "parameters": { + "action": "unlabeled" + } }, { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "api-ready-for-review" - } - } - ] + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Michael / Tanner - PRs", + "isOrgProject": true + } } ] } @@ -10439,6 +12781,66 @@ } } ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + } + ] + } + ] } ] } @@ -10579,21 +12981,81 @@ "operator": "not", "operands": [ { - "name": "isInProject", + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Michael / Tanner - PRs", + "isOrgProject": true + } + } + ] + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Michael / Tanner - PRs", + "columnName": "Done", + "isOrgProject": true + } + } + ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", "parameters": { - "projectName": "Area Pod: Michael / Tanner - PRs", - "isOrgProject": true + "label": "os-ios" } } ] }, { - "name": "isInProjectColumn", - "parameters": { - "projectName": "Area Pod: Michael / Tanner - PRs", - "columnName": "Done", - "isOrgProject": true - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + } + ] } ] } @@ -10921,6 +13383,89 @@ } } }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "taskName": "[Area Pod: Michael / Tanner - PRs] Excluded", + "actions": [ + { + "name": "removeFromProject", + "parameters": { + "projectName": "Area Pod: Michael / Tanner - PRs", + "isOrgProject": true + } + } + ], + "eventType": "pull_request", + "eventNames": [ + "pull_request" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Michael / Tanner - PRs", + "isOrgProject": true + } + }, + { + "operator": "not", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Michael / Tanner - PRs", + "columnName": "Done", + "isOrgProject": true + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + } + ] + } + ] + } + } + }, { "taskSource": "fabricbot-config", "taskType": "trigger", @@ -14658,6 +17203,77 @@ } } ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" + } + } + ] + } + ] } ] } @@ -14734,21 +17350,92 @@ "operator": "not", "operands": [ { - "name": "isInProject", + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Eric / Jeff - Issue Triage", + "isOrgProject": true + } + } + ] + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Eric / Jeff - Issue Triage", + "columnName": "Triaged", + "isOrgProject": true + } + } + ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", "parameters": { - "projectName": "Area Pod: Eric / Jeff - Issue Triage", - "isOrgProject": true + "label": "os-tvos" } } ] }, { - "name": "isInProjectColumn", - "parameters": { - "projectName": "Area Pod: Eric / Jeff - Issue Triage", - "columnName": "Triaged", - "isOrgProject": true - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" + } + } + ] } ] } @@ -14865,37 +17552,42 @@ } }, { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "and", "operands": [ { - "name": "isInMilestone", + "name": "isOpen", "parameters": {} - } - ] - }, - { - "operator": "not", - "operands": [ + }, { - "name": "hasLabel", - "parameters": { - "label": "needs-author-action" - } - } - ] - }, - { - "operator": "not", - "operands": [ + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + }, { - "name": "hasLabel", - "parameters": { - "label": "api-ready-for-review" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] } ] } @@ -14943,37 +17635,208 @@ } }, { - "name": "isOpen", - "parameters": {} + "operator": "and", + "operands": [ + { + "name": "isOpen", + "parameters": {} + }, + { + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] + } + ] + } + ] + } + } + }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "taskName": "[Area Pod: Eric / Jeff - Issue Triage] Jeff Updated Issue", + "actions": [ + { + "name": "moveToProjectColumn", + "parameters": { + "projectName": "Area Pod: Eric / Jeff - Issue Triage", + "columnName": "Triage: Jeff", + "isOrgProject": true + } + } + ], + "eventType": "issue", + "eventNames": [ + "issues" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Eric / Jeff - Issue Triage", + "isOrgProject": true, + "columnName": "Needs Triage" + } }, { - "operator": "not", + "name": "isActivitySender", + "parameters": { + "user": "jeffhandley" + } + }, + { + "operator": "and", "operands": [ { - "name": "isInMilestone", + "name": "isOpen", "parameters": {} + }, + { + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] } ] + } + ] + } + } + }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssueCommentResponder", + "version": "1.0", + "config": { + "taskName": "[Area Pod: Eric / Jeff - Issue Triage] Jeff Commented", + "actions": [ + { + "name": "moveToProjectColumn", + "parameters": { + "projectName": "Area Pod: Eric / Jeff - Issue Triage", + "columnName": "Triage: Jeff", + "isOrgProject": true + } + } + ], + "eventType": "issue", + "eventNames": [ + "issue_comment" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Eric / Jeff - Issue Triage", + "isOrgProject": true, + "columnName": "Needs Triage" + } }, { - "operator": "not", + "name": "isActivitySender", + "parameters": { + "user": "jeffhandley" + } + }, + { + "operator": "and", "operands": [ { - "name": "hasLabel", - "parameters": { - "label": "needs-author-action" - } - } - ] - }, - { - "operator": "not", - "operands": [ + "name": "isOpen", + "parameters": {} + }, + { + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] + }, { - "name": "hasLabel", - "parameters": { - "label": "api-ready-for-review" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] } ] } @@ -14988,13 +17851,12 @@ "subCapability": "IssuesOnlyResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Eric / Jeff - Issue Triage] Jeff Updated Issue", + "taskName": "[Area Pod: Eric / Jeff - Issue Triage] Excluded", "actions": [ { - "name": "moveToProjectColumn", + "name": "removeFromProject", "parameters": { "projectName": "Area Pod: Eric / Jeff - Issue Triage", - "columnName": "Triage: Jeff", "isOrgProject": true } } @@ -15007,50 +17869,49 @@ "operator": "and", "operands": [ { - "name": "isInProjectColumn", + "name": "isInProject", "parameters": { "projectName": "Area Pod: Eric / Jeff - Issue Triage", - "isOrgProject": true, - "columnName": "Needs Triage" - } - }, - { - "name": "isActivitySender", - "parameters": { - "user": "jeffhandley" + "isOrgProject": true } }, { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "or", "operands": [ { - "name": "isInMilestone", - "parameters": {} - } - ] - }, - { - "operator": "not", - "operands": [ + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + }, { "name": "hasLabel", "parameters": { - "label": "needs-author-action" + "label": "os-maccatalyst" } - } - ] - }, - { - "operator": "not", - "operands": [ + }, { "name": "hasLabel", "parameters": { - "label": "api-ready-for-review" + "label": "os-ios" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" } } ] @@ -15063,75 +17924,65 @@ "taskSource": "fabricbot-config", "taskType": "trigger", "capabilityId": "IssueResponder", - "subCapability": "IssueCommentResponder", + "subCapability": "IssuesOnlyResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Eric / Jeff - Issue Triage] Jeff Commented", + "taskName": "[Area Pod: Eric / Jeff - PRs] Moved to Another Area", "actions": [ { - "name": "moveToProjectColumn", + "name": "removeFromProject", "parameters": { - "projectName": "Area Pod: Eric / Jeff - Issue Triage", - "columnName": "Triage: Jeff", + "projectName": "Area Pod: Eric / Jeff - PRs", "isOrgProject": true } } ], - "eventType": "issue", + "eventType": "pull_request", "eventNames": [ - "issue_comment" + "pull_request" ], "conditions": { "operator": "and", "operands": [ { - "name": "isInProjectColumn", - "parameters": { - "projectName": "Area Pod: Eric / Jeff - Issue Triage", - "isOrgProject": true, - "columnName": "Needs Triage" - } - }, - { - "name": "isActivitySender", - "parameters": { - "user": "jeffhandley" - } - }, - { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "and", "operands": [ { - "name": "isInMilestone", - "parameters": {} + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "area-Meta" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-area-label" + } + } + ] } ] }, { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "needs-author-action" - } - } - ] + "name": "isAction", + "parameters": { + "action": "unlabeled" + } }, { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "api-ready-for-review" - } - } - ] + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Eric / Jeff - PRs", + "isOrgProject": true + } } ] } @@ -15339,14 +18190,85 @@ } } ] - }, - { - "name": "isInProjectColumn", - "parameters": { - "projectName": "Area Pod: Eric / Jeff - PRs", - "columnName": "Done", - "isOrgProject": true - } + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Eric / Jeff - PRs", + "columnName": "Done", + "isOrgProject": true + } + } + ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" + } + } + ] } ] } @@ -15464,6 +18386,77 @@ } } ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" + } + } + ] + } + ] } ] } @@ -15705,6 +18698,95 @@ } } }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "taskName": "[Area Pod: Eric / Jeff - PRs] Excluded", + "actions": [ + { + "name": "removeFromProject", + "parameters": { + "projectName": "Area Pod: Eric / Jeff - PRs", + "isOrgProject": true + } + } + ], + "eventType": "pull_request", + "eventNames": [ + "pull_request" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Eric / Jeff - PRs", + "isOrgProject": true + } + }, + { + "operator": "not", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Eric / Jeff - PRs", + "columnName": "Done", + "isOrgProject": true + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" + } + } + ] + } + ] + } + } + }, { "taskSource": "fabricbot-config", "taskType": "trigger", @@ -15860,41 +18942,112 @@ } }, { - "name": "labelAdded", + "name": "labelAdded", + "parameters": { + "label": "code-analyzer" + } + } + ] + } + ] + }, + { + "name": "isOpen", + "parameters": {} + }, + { + "operator": "or", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Libraries Analyzers - Issue Triage", + "isOrgProject": true + } + } + ] + }, + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Libraries Analyzers - Issue Triage", + "isOrgProject": true, + "columnName": "Triaged" + } + } + ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", "parameters": { - "label": "code-analyzer" + "label": "os-tvos" } } ] - } - ] - }, - { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "or", - "operands": [ + }, { "operator": "not", "operands": [ { - "name": "isInProject", + "name": "hasLabel", "parameters": { - "projectName": "Area Pod: Libraries Analyzers - Issue Triage", - "isOrgProject": true + "label": "arch-wasm" } } ] - }, - { - "name": "isInProjectColumn", - "parameters": { - "projectName": "Area Pod: Libraries Analyzers - Issue Triage", - "isOrgProject": true, - "columnName": "Triaged" - } } ] } @@ -15990,6 +19143,77 @@ } } ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" + } + } + ] + } + ] } ] } @@ -16071,13 +19295,179 @@ "subCapability": "IssuesOnlyResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Libraries Analyzers - Issue Triage] Buyaa Updated Issue", + "taskName": "[Area Pod: Libraries Analyzers - Issue Triage] Buyaa Updated Issue", + "actions": [ + { + "name": "moveToProjectColumn", + "parameters": { + "projectName": "Area Pod: Libraries Analyzers - Issue Triage", + "columnName": "Triage: Buyaa", + "isOrgProject": true + } + } + ], + "eventType": "issue", + "eventNames": [ + "issues" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Libraries Analyzers - Issue Triage", + "isOrgProject": true, + "columnName": "Needs Triage" + } + }, + { + "name": "isActivitySender", + "parameters": { + "user": "buyaa-n" + } + }, + { + "operator": "and", + "operands": [ + { + "name": "isOpen", + "parameters": {} + }, + { + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] + } + ] + } + ] + } + } + }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssueCommentResponder", + "version": "1.0", + "config": { + "taskName": "[Area Pod: Libraries Analyzers - Issue Triage] Buyaa Commented", + "actions": [ + { + "name": "moveToProjectColumn", + "parameters": { + "projectName": "Area Pod: Libraries Analyzers - Issue Triage", + "columnName": "Triage: Buyaa", + "isOrgProject": true + } + } + ], + "eventType": "issue", + "eventNames": [ + "issue_comment" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Libraries Analyzers - Issue Triage", + "isOrgProject": true, + "columnName": "Needs Triage" + } + }, + { + "name": "isActivitySender", + "parameters": { + "user": "buyaa-n" + } + }, + { + "operator": "and", + "operands": [ + { + "name": "isOpen", + "parameters": {} + }, + { + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] + } + ] + } + ] + } + } + }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "IssuesOnlyResponder", + "version": "1.0", + "config": { + "taskName": "[Area Pod: Libraries Analyzers - Issue Triage] Carlos Updated Issue", "actions": [ { "name": "moveToProjectColumn", "parameters": { "projectName": "Area Pod: Libraries Analyzers - Issue Triage", - "columnName": "Triage: Buyaa", + "columnName": "Triage: Carlos", "isOrgProject": true } } @@ -16100,41 +19490,46 @@ { "name": "isActivitySender", "parameters": { - "user": "buyaa-n" + "user": "carlossanlop" } }, { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "and", "operands": [ { - "name": "isInMilestone", + "name": "isOpen", "parameters": {} - } - ] - }, - { - "operator": "not", - "operands": [ + }, { - "name": "hasLabel", - "parameters": { - "label": "needs-author-action" - } - } - ] - }, - { - "operator": "not", - "operands": [ + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + }, { - "name": "hasLabel", - "parameters": { - "label": "api-ready-for-review" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] } ] } @@ -16149,13 +19544,13 @@ "subCapability": "IssueCommentResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Libraries Analyzers - Issue Triage] Buyaa Commented", + "taskName": "[Area Pod: Libraries Analyzers - Issue Triage] Carlos Commented", "actions": [ { "name": "moveToProjectColumn", "parameters": { "projectName": "Area Pod: Libraries Analyzers - Issue Triage", - "columnName": "Triage: Buyaa", + "columnName": "Triage: Carlos", "isOrgProject": true } } @@ -16178,41 +19573,46 @@ { "name": "isActivitySender", "parameters": { - "user": "buyaa-n" + "user": "carlossanlop" } }, { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "and", "operands": [ { - "name": "isInMilestone", + "name": "isOpen", "parameters": {} - } - ] - }, - { - "operator": "not", - "operands": [ + }, { - "name": "hasLabel", - "parameters": { - "label": "needs-author-action" - } - } - ] - }, - { - "operator": "not", - "operands": [ + "operator": "not", + "operands": [ + { + "name": "isInMilestone", + "parameters": {} + } + ] + }, { - "name": "hasLabel", - "parameters": { - "label": "api-ready-for-review" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "needs-author-action" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "api-ready-for-review" + } + } + ] } ] } @@ -16227,13 +19627,12 @@ "subCapability": "IssuesOnlyResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Libraries Analyzers - Issue Triage] Carlos Updated Issue", + "taskName": "[Area Pod: Libraries Analyzers - Issue Triage] Excluded", "actions": [ { - "name": "moveToProjectColumn", + "name": "removeFromProject", "parameters": { "projectName": "Area Pod: Libraries Analyzers - Issue Triage", - "columnName": "Triage: Carlos", "isOrgProject": true } } @@ -16246,50 +19645,49 @@ "operator": "and", "operands": [ { - "name": "isInProjectColumn", + "name": "isInProject", "parameters": { "projectName": "Area Pod: Libraries Analyzers - Issue Triage", - "isOrgProject": true, - "columnName": "Needs Triage" - } - }, - { - "name": "isActivitySender", - "parameters": { - "user": "carlossanlop" + "isOrgProject": true } }, { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "or", "operands": [ { - "name": "isInMilestone", - "parameters": {} - } - ] - }, - { - "operator": "not", - "operands": [ + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + }, { "name": "hasLabel", "parameters": { - "label": "needs-author-action" + "label": "os-maccatalyst" } - } - ] - }, - { - "operator": "not", - "operands": [ + }, { "name": "hasLabel", "parameters": { - "label": "api-ready-for-review" + "label": "os-ios" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" } } ] @@ -16302,75 +19700,65 @@ "taskSource": "fabricbot-config", "taskType": "trigger", "capabilityId": "IssueResponder", - "subCapability": "IssueCommentResponder", + "subCapability": "IssuesOnlyResponder", "version": "1.0", "config": { - "taskName": "[Area Pod: Libraries Analyzers - Issue Triage] Carlos Commented", + "taskName": "[Area Pod: Libraries Analyzers - PRs] Moved to Another Area", "actions": [ { - "name": "moveToProjectColumn", + "name": "removeFromProject", "parameters": { - "projectName": "Area Pod: Libraries Analyzers - Issue Triage", - "columnName": "Triage: Carlos", + "projectName": "Area Pod: Libraries Analyzers - PRs", "isOrgProject": true } } ], - "eventType": "issue", + "eventType": "pull_request", "eventNames": [ - "issue_comment" + "pull_request" ], "conditions": { "operator": "and", "operands": [ { - "name": "isInProjectColumn", - "parameters": { - "projectName": "Area Pod: Libraries Analyzers - Issue Triage", - "isOrgProject": true, - "columnName": "Needs Triage" - } - }, - { - "name": "isActivitySender", - "parameters": { - "user": "carlossanlop" - } - }, - { - "name": "isOpen", - "parameters": {} - }, - { - "operator": "not", + "operator": "and", "operands": [ { - "name": "isInMilestone", - "parameters": {} - } - ] - }, - { - "operator": "not", - "operands": [ + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "code-fixer" + } + } + ] + }, { - "name": "hasLabel", - "parameters": { - "label": "needs-author-action" - } + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "code-analyzer" + } + } + ] } ] }, { - "operator": "not", - "operands": [ - { - "name": "hasLabel", - "parameters": { - "label": "api-ready-for-review" - } - } - ] + "name": "isAction", + "parameters": { + "action": "unlabeled" + } + }, + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Libraries Analyzers - PRs", + "isOrgProject": true + } } ] } @@ -16588,6 +19976,77 @@ } } ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" + } + } + ] + } + ] } ] } @@ -16703,6 +20162,77 @@ } } ] + }, + { + "operator": "and", + "operands": [ + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + } + ] + }, + { + "operator": "not", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" + } + } + ] + } + ] } ] } @@ -16943,5 +20473,94 @@ ] } } + }, + { + "taskSource": "fabricbot-config", + "taskType": "trigger", + "capabilityId": "IssueResponder", + "subCapability": "PullRequestResponder", + "version": "1.0", + "config": { + "taskName": "[Area Pod: Libraries Analyzers - PRs] Excluded", + "actions": [ + { + "name": "removeFromProject", + "parameters": { + "projectName": "Area Pod: Libraries Analyzers - PRs", + "isOrgProject": true + } + } + ], + "eventType": "pull_request", + "eventNames": [ + "pull_request" + ], + "conditions": { + "operator": "and", + "operands": [ + { + "name": "isInProject", + "parameters": { + "projectName": "Area Pod: Libraries Analyzers - PRs", + "isOrgProject": true + } + }, + { + "operator": "not", + "operands": [ + { + "name": "isInProjectColumn", + "parameters": { + "projectName": "Area Pod: Libraries Analyzers - PRs", + "columnName": "Done", + "isOrgProject": true + } + } + ] + }, + { + "operator": "or", + "operands": [ + { + "name": "hasLabel", + "parameters": { + "label": "os-android" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-maccatalyst" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-ios" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tizen" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "os-tvos" + } + }, + { + "name": "hasLabel", + "parameters": { + "label": "arch-wasm" + } + } + ] + } + ] + } + } } -] +] \ No newline at end of file diff --git a/docs/area-owners.json b/docs/area-owners.json index 5be050f85b13b9..8904656472f6bb 100644 --- a/docs/area-owners.json +++ b/docs/area-owners.json @@ -248,7 +248,7 @@ "label": "area-Diagnostics-mono" }, { - "lead": "marek-safar", + "lead": "SamMonoRT", "owners": [ "lambdageek" ], diff --git a/docs/area-owners.md b/docs/area-owners.md index 6a2e4e3714e5af..897cfde9638aed 100644 --- a/docs/area-owners.md +++ b/docs/area-owners.md @@ -26,7 +26,7 @@ Note: Editing this file doesn't update the mapping used by `@msftbot` for area-s | area-DependencyModel | @ericstj | @dotnet/area-dependencymodel | Included: | | area-Diagnostics-coreclr | @tommcdon | @tommcdon | | | area-Diagnostics-mono | @steveisok | @lateralusX @mdh1418 | | -| area-EnC-mono | @marek-safar | @lambdageek | Hot Reload on WebAssembly, Android, iOS, etc | +| area-EnC-mono | @SamMonoRT | @lambdageek | Hot Reload on WebAssembly, Android, iOS, etc | | area-ExceptionHandling-coreclr | @mangod9 | @janvorli | | | area-Extensions-Caching | @ericstj | @dotnet/area-extensions-caching | | | area-Extensions-Configuration | @ericstj | @dotnet/area-extensions-configuration | | diff --git a/docs/design/coreclr/botr/readytorun-format.md b/docs/design/coreclr/botr/readytorun-format.md index 2c63997332e487..d68099747d8f66 100644 --- a/docs/design/coreclr/botr/readytorun-format.md +++ b/docs/design/coreclr/botr/readytorun-format.md @@ -179,6 +179,7 @@ The following section types are defined and described later in this document: | PgoInstrumentationData | 117 | Image (added in V5.2) | ManifestAssemblyMvids | 118 | Image (added in V5.3) | CrossModuleInlineInfo | 119 | Image (added in V6.3) +| HotColdMap | 120 | Image (added in V8.0) ## ReadyToRunSectionType.CompilerIdentifier @@ -644,6 +645,15 @@ The entry of the hashtable is a counted sequence of compressed unsigned integers This section may be included in addition to a InliningInfo2 section. +## ReadyToRunSectionType.HotColdMap (v8.0+) +In ReadyToRun 8.0+, the format supports splitting a method into hot and cold parts so that they are not located together. This hot-cold map section captures the information about how methods are split so that the runtime can locate them for various services. + +For every method that is split, there is a single entry in the section. Each entry has two unsigned 32-bit integers. The first integer is the runtime function index of the cold part and the second integer is the runtime function index of the hot part. + +The methods in this table are sorted by their hot part runtime function indices, which are also sorted by their cold part runtime function indices because we always emit the cold part in the same order as the hot parts, or by their RVAs because the runtime function table itself is sorted by the RVAs. + +This section may not exist if no method is split - this happens when the `--hot-cold-splitting` flag is not specified during compilation, or the compiler decides it should not split any methods. + # Native Format Native format is set of encoding patterns that allow persisting type system data in a binary format that is diff --git a/docs/design/features/hybrid-globalization.md b/docs/design/features/globalization-hybrid-mode.md similarity index 89% rename from docs/design/features/hybrid-globalization.md rename to docs/design/features/globalization-hybrid-mode.md index 5d08676ea642e4..0e6ed5d7c1e7f2 100644 --- a/docs/design/features/hybrid-globalization.md +++ b/docs/design/features/globalization-hybrid-mode.md @@ -1,6 +1,11 @@ # Hybrid Globalization -Description, purpose and instruction how to use. +Originally, internalization data is loaded from ICU data files. In `HybridGlobalization` mode we are leveraging the platform-native internationalization APIs, where it is possible, to allow for loading smaller ICU data files. We still need to rely on ICU files because for a bunch of globalization data no API equivalent is available. For some existing equivalents, the behavior does not fully match the original. The differences you can expect after switching on the mode are listed in this document. Expected size savings can be found under each platform section below. + +Hybrid has lower priority than Invariant. To switch on the mode set the property in the build file: +``` +true +``` ## Behavioral differences @@ -8,7 +13,9 @@ Hybrid mode does not use ICU data for some functions connected with globalizatio ### WASM -For WebAssembly in Browser we are using Web API instead of some ICU data. Ideally, we would use `System.Runtime.InteropServices.JavaScript` to call JS code from inside of C# but we cannot reference any assemblies from inside of `System.Private.CoreLib`. That is why we are using iCalls instead. +For WebAssembly in Browser we are using Web API instead of some ICU data. Ideally, we would use `System.Runtime.InteropServices.JavaScript` to call JS code from inside of C# but we cannot reference any assemblies from inside of `System.Private.CoreLib`. That is why we are using iCalls instead. The host support depends on used Web API functions support - see **dependencies** in each section. + +Hybrid has higher priority than sharding or custom modes, described in globalization-icu-wasm.md. **SortKey** @@ -33,6 +40,12 @@ Hybrid case change, same as ICU-based, does not support code points expansion e. ICU-based case change does not respect final-sigma rule, but hybrid does, so "ΒΌΛΟΣ" -> "βόλος", not "βόλοσ". +Dependencies: +- [String.prototype.toUpperCase()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toUpperCase) +- [String.prototype.toLoweCase()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLowerCase) +- [String.prototype.toLocaleUpperCase()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLocaleUpperCase) +- [String.prototype.toLocaleLoweCase()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/toLocaleLowerCase) + **String comparison** Affected public APIs: @@ -40,8 +53,12 @@ Affected public APIs: - String.Compare, - String.Equals. +Dependencies: +- [String.prototype.localeCompare()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare) + The number of `CompareOptions` and `StringComparison` combinations is limited. Originally supported combinations can be found [here for CompareOptions](https://learn.microsoft.com/dotnet/api/system.globalization.compareoptions) and [here for StringComparison](https://learn.microsoft.com/dotnet/api/system.stringcomparison). + - `IgnoreWidth` is not supported because there is no equivalent in Web API. Throws `PlatformNotSupportedException`. ``` JS let high = String.fromCharCode(65281) // %uff83 = テ @@ -196,6 +213,10 @@ Affected public APIs: - String.StartsWith - String.EndsWith +Dependencies: +- [String.prototype.normalize()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/normalize) +- [String.prototype.localeCompare()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare) + Web API does not expose locale-sensitive endsWith/startsWith function. As a workaround, both strings get normalized and weightless characters are removed. Resulting strings are cut to the same length and comparison is performed. This approach, beyond having the same compare option limitations as described under **String comparison**, has additional limitations connected with the workaround used. Because we are normalizing strings to be able to cut them, we cannot calculate the match length on the original strings. Methods that calculate this information throw PlatformNotSupported exception: - [CompareInfo.IsPrefix](https://learn.microsoft.com/en-us/dotnet/api/system.globalization.compareinfo.isprefix?view=net-8.0#system-globalization-compareinfo-isprefix(system-readonlyspan((system-char))-system-readonlyspan((system-char))-system-globalization-compareoptions-system-int32@)) diff --git a/docs/project/list-of-diagnostics.md b/docs/project/list-of-diagnostics.md index 7c814cdf68ae87..d6783d80ecf90a 100644 --- a/docs/project/list-of-diagnostics.md +++ b/docs/project/list-of-diagnostics.md @@ -219,8 +219,8 @@ The diagnostic id values reserved for .NET Libraries analyzer warnings are `SYSL | __`SYSLIB1100`__ | Configuration binding generator: type is not supported. | | __`SYSLIB1101`__ | Configuration binding generator: property on type is not supported. | | __`SYSLIB1102`__ | Configuration binding generator: project's language version must be at least C# 11.| -| __`SYSLIB1103`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* | -| __`SYSLIB1104`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* | +| __`SYSLIB1103`__ | Configuration binding generator: value types are invalid inputs to configuration 'Bind' methods.* | +| __`SYSLIB1104`__ | Configuration binding generator: Generator cannot determine the target configuration type.* | | __`SYSLIB1105`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* | | __`SYSLIB1106`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* | | __`SYSLIB1107`__ | *_`SYSLIB1100`-`SYSLIB1118` reserved for Microsoft.Extensions.Configuration.Binder.SourceGeneration.* | diff --git a/eng/CodeAnalysis.src.globalconfig b/eng/CodeAnalysis.src.globalconfig index d83299c431cce5..0fdc74157b6c6a 100644 --- a/eng/CodeAnalysis.src.globalconfig +++ b/eng/CodeAnalysis.src.globalconfig @@ -471,6 +471,9 @@ dotnet_diagnostic.CA1859.severity = warning # CA1860: Avoid using 'Enumerable.Any()' extension method dotnet_diagnostic.CA1860.severity = warning +# CA1861: Avoid constant arrays as arguments +dotnet_diagnostic.CA1861.severity = warning + # CA2000: Dispose objects before losing scope dotnet_diagnostic.CA2000.severity = none diff --git a/eng/CodeAnalysis.test.globalconfig b/eng/CodeAnalysis.test.globalconfig index 84c7837a7e536a..ae1dc7eb9872fc 100644 --- a/eng/CodeAnalysis.test.globalconfig +++ b/eng/CodeAnalysis.test.globalconfig @@ -468,6 +468,9 @@ dotnet_diagnostic.CA1859.severity = none # CA1860: Avoid using 'Enumerable.Any()' extension method dotnet_diagnostic.CA1860.severity = none +# CA1861: Avoid constant arrays as arguments +dotnet_diagnostic.CA1861.severity = none + # CA2000: Dispose objects before losing scope dotnet_diagnostic.CA2000.severity = none diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index b2d2ecbd58066b..b55a2045949060 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,8 +1,8 @@ - + https://github.com/dotnet/icu - 389d19d09d3cf16ec0143dba065fcd704ab8e48c + d77dd854ec4d9a3c4a0c584421ee393642d631ef https://github.com/dotnet/msquic @@ -12,29 +12,29 @@ https://github.com/dotnet/wcf 7f504aabb1988e9a093c1e74d8040bd52feb2f01 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 https://github.com/dotnet/llvm-project @@ -44,29 +44,29 @@ https://github.com/dotnet/llvm-project 76f334f354eb653a7b409a5319b591ea09df5a43 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 https://github.com/dotnet/llvm-project @@ -85,14 +85,14 @@ 8374d5fca634a93458c84414b1604c12f765d1ab - + https://github.com/dotnet/cecil - f283c6229347f2dc3a25b04f6611014d8871d0b0 + ea84c8236c45ebace0073dbc01e0e75ffba65a65 - + https://github.com/dotnet/emsdk - fb9e15863c4a8b4fa209096f29406cc6dbb8ef32 + 63af043d58bd8d471da0e236e6255611e061cc4e @@ -107,9 +107,9 @@ - + https://github.com/dotnet/arcade - f4269875971171c278c2cd695e9ef94b6516e4be + 234e0726c7384ee84bf08550f2d16a1ff2d5c543 @@ -117,166 +117,166 @@ 54eb3b811c57f5e94617d31a102fc9cb664ccdd5 - + https://github.com/dotnet/xliff-tasks - 9e7fbcab4e5275f63c0cd37553ba426de9194309 + 8fd12314c3e648c03a4189ba0bd1c3b09f5d6a01 - + https://github.com/dotnet/arcade - f4269875971171c278c2cd695e9ef94b6516e4be + 234e0726c7384ee84bf08550f2d16a1ff2d5c543 - + https://github.com/dotnet/arcade - f4269875971171c278c2cd695e9ef94b6516e4be + 234e0726c7384ee84bf08550f2d16a1ff2d5c543 - + https://github.com/dotnet/arcade - f4269875971171c278c2cd695e9ef94b6516e4be + 234e0726c7384ee84bf08550f2d16a1ff2d5c543 - + https://github.com/dotnet/arcade - f4269875971171c278c2cd695e9ef94b6516e4be + 234e0726c7384ee84bf08550f2d16a1ff2d5c543 - + https://github.com/dotnet/arcade - f4269875971171c278c2cd695e9ef94b6516e4be + 234e0726c7384ee84bf08550f2d16a1ff2d5c543 - + https://github.com/dotnet/arcade - f4269875971171c278c2cd695e9ef94b6516e4be + 234e0726c7384ee84bf08550f2d16a1ff2d5c543 - + https://github.com/dotnet/arcade - f4269875971171c278c2cd695e9ef94b6516e4be + 234e0726c7384ee84bf08550f2d16a1ff2d5c543 - + https://github.com/dotnet/arcade - f4269875971171c278c2cd695e9ef94b6516e4be + 234e0726c7384ee84bf08550f2d16a1ff2d5c543 - + https://github.com/dotnet/arcade - f4269875971171c278c2cd695e9ef94b6516e4be + 234e0726c7384ee84bf08550f2d16a1ff2d5c543 - + https://github.com/dotnet/arcade - f4269875971171c278c2cd695e9ef94b6516e4be + 234e0726c7384ee84bf08550f2d16a1ff2d5c543 - + https://github.com/dotnet/arcade - f4269875971171c278c2cd695e9ef94b6516e4be + 234e0726c7384ee84bf08550f2d16a1ff2d5c543 - + https://github.com/dotnet/arcade - f4269875971171c278c2cd695e9ef94b6516e4be + 234e0726c7384ee84bf08550f2d16a1ff2d5c543 - + https://github.com/dotnet/arcade - f4269875971171c278c2cd695e9ef94b6516e4be + 234e0726c7384ee84bf08550f2d16a1ff2d5c543 - + https://github.com/dotnet/arcade - f4269875971171c278c2cd695e9ef94b6516e4be + 234e0726c7384ee84bf08550f2d16a1ff2d5c543 - + https://github.com/dotnet/arcade - f4269875971171c278c2cd695e9ef94b6516e4be + 234e0726c7384ee84bf08550f2d16a1ff2d5c543 - + https://github.com/dotnet/arcade - f4269875971171c278c2cd695e9ef94b6516e4be + 234e0726c7384ee84bf08550f2d16a1ff2d5c543 - + https://github.com/dotnet/runtime-assets - 886b608e3f566153c047ba0fd31357404365ae4c + 32bcf870359408a0cd6f325b558d744f5bf56c93 - + https://github.com/dotnet/runtime-assets - 886b608e3f566153c047ba0fd31357404365ae4c + 32bcf870359408a0cd6f325b558d744f5bf56c93 - + https://github.com/dotnet/runtime-assets - 886b608e3f566153c047ba0fd31357404365ae4c + 32bcf870359408a0cd6f325b558d744f5bf56c93 - + https://github.com/dotnet/runtime-assets - 886b608e3f566153c047ba0fd31357404365ae4c + 32bcf870359408a0cd6f325b558d744f5bf56c93 - + https://github.com/dotnet/runtime-assets - 886b608e3f566153c047ba0fd31357404365ae4c + 32bcf870359408a0cd6f325b558d744f5bf56c93 - + https://github.com/dotnet/runtime-assets - 886b608e3f566153c047ba0fd31357404365ae4c + 32bcf870359408a0cd6f325b558d744f5bf56c93 - + https://github.com/dotnet/runtime-assets - 886b608e3f566153c047ba0fd31357404365ae4c + 32bcf870359408a0cd6f325b558d744f5bf56c93 - + https://github.com/dotnet/runtime-assets - 886b608e3f566153c047ba0fd31357404365ae4c + 32bcf870359408a0cd6f325b558d744f5bf56c93 - + https://github.com/dotnet/runtime-assets - 886b608e3f566153c047ba0fd31357404365ae4c + 32bcf870359408a0cd6f325b558d744f5bf56c93 - + https://github.com/dotnet/runtime-assets - 886b608e3f566153c047ba0fd31357404365ae4c + 32bcf870359408a0cd6f325b558d744f5bf56c93 - + https://github.com/dotnet/runtime-assets - 886b608e3f566153c047ba0fd31357404365ae4c + 32bcf870359408a0cd6f325b558d744f5bf56c93 - + https://github.com/dotnet/runtime-assets - 886b608e3f566153c047ba0fd31357404365ae4c + 32bcf870359408a0cd6f325b558d744f5bf56c93 - + https://github.com/dotnet/runtime-assets - 886b608e3f566153c047ba0fd31357404365ae4c + 32bcf870359408a0cd6f325b558d744f5bf56c93 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 - + https://github.com/dotnet/llvm-project - c01ca3bc8a420b3796d816c43bdd06e337c72ea6 + 43fe12a7a5f6917dee47ca4de17477ed1ac2c312 https://github.com/dotnet/runtime @@ -303,58 +303,58 @@ https://github.com/dotnet/runtime 93da0c966f9bc537dd77fbe2cbeb0bec4ff6a48b - + https://github.com/dotnet/xharness - 5d3b745c64e8092c2ce3ce1feca85d87d814f292 + 230501dc45d8c96e995ceed1189852eb0ee08693 - + https://github.com/dotnet/xharness - 5d3b745c64e8092c2ce3ce1feca85d87d814f292 + 230501dc45d8c96e995ceed1189852eb0ee08693 - + https://github.com/dotnet/xharness - 5d3b745c64e8092c2ce3ce1feca85d87d814f292 + 230501dc45d8c96e995ceed1189852eb0ee08693 - + https://github.com/dotnet/arcade - f4269875971171c278c2cd695e9ef94b6516e4be + 234e0726c7384ee84bf08550f2d16a1ff2d5c543 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - c85736cdab833e3cefa202f5e7e28f1fb6543604 + b9af49c3ae71595e30d893960d9b2cecf83c9743 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - c85736cdab833e3cefa202f5e7e28f1fb6543604 + b9af49c3ae71595e30d893960d9b2cecf83c9743 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - c85736cdab833e3cefa202f5e7e28f1fb6543604 + b9af49c3ae71595e30d893960d9b2cecf83c9743 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - c85736cdab833e3cefa202f5e7e28f1fb6543604 + b9af49c3ae71595e30d893960d9b2cecf83c9743 - + https://github.com/dotnet/hotreload-utils - 38e5743db0070214e73fa04ed1524a254be95c1a + 1eec66c6cff38ddf124c6c740b9ccbe2a1144352 - + https://github.com/dotnet/runtime-assets - 886b608e3f566153c047ba0fd31357404365ae4c + 32bcf870359408a0cd6f325b558d744f5bf56c93 - + https://github.com/dotnet/roslyn - 0cb0d5796b336c6a746e6d14c129f2e2b44f4f5e + fb8455f2f9046b821b826aab81bf8faa00711065 - + https://github.com/dotnet/roslyn - 0cb0d5796b336c6a746e6d14c129f2e2b44f4f5e + fb8455f2f9046b821b826aab81bf8faa00711065 - + https://github.com/dotnet/roslyn - 0cb0d5796b336c6a746e6d14c129f2e2b44f4f5e + fb8455f2f9046b821b826aab81bf8faa00711065 https://github.com/dotnet/roslyn-analyzers @@ -364,18 +364,18 @@ https://github.com/dotnet/roslyn-analyzers 2b6ab8d727ce73a78bcbf026ac75ea8a7c804daf - + https://github.com/dotnet/sdk - 2fd62c3936f5336b836f6b12df170aa0e90da767 + dfdec2edb38ee24c5551125e1cdf12cf6117b6a7 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - c85736cdab833e3cefa202f5e7e28f1fb6543604 + b9af49c3ae71595e30d893960d9b2cecf83c9743 - + https://dev.azure.com/dnceng/internal/_git/dotnet-optimization - c85736cdab833e3cefa202f5e7e28f1fb6543604 + b9af49c3ae71595e30d893960d9b2cecf83c9743 diff --git a/eng/Versions.props b/eng/Versions.props index 38116216008637..5e154a36b58b3b 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -40,9 +40,9 @@ Any tools that contribute to the design-time experience should use the MicrosoftCodeAnalysisVersion_LatestVS property above to ensure they do not break the local dev experience. --> - 4.7.0-1.23269.2 - 4.7.0-1.23269.2 - 4.7.0-1.23269.2 + 4.7.0-2.23301.9 + 4.7.0-2.23301.9 + 4.7.0-2.23301.9 - 8.0.100-preview.2.23107.1 + 8.0.100-preview.6.23303.2 - 8.0.0-beta.23268.1 - 8.0.0-beta.23268.1 - 8.0.0-beta.23268.1 - 8.0.0-beta.23268.1 - 8.0.0-beta.23268.1 - 2.5.1-beta.23268.1 - 8.0.0-beta.23268.1 - 8.0.0-beta.23268.1 - 8.0.0-beta.23268.1 - 8.0.0-beta.23268.1 - 8.0.0-beta.23268.1 - 8.0.0-beta.23268.1 - 8.0.0-beta.23268.1 - 8.0.0-beta.23268.1 - 8.0.0-beta.23268.1 + 8.0.0-beta.23302.3 + 8.0.0-beta.23302.3 + 8.0.0-beta.23302.3 + 8.0.0-beta.23302.3 + 8.0.0-beta.23302.3 + 2.5.1-beta.23302.3 + 8.0.0-beta.23302.3 + 8.0.0-beta.23302.3 + 8.0.0-beta.23302.3 + 8.0.0-beta.23302.3 + 8.0.0-beta.23302.3 + 8.0.0-beta.23302.3 + 8.0.0-beta.23302.3 + 8.0.0-beta.23302.3 + 8.0.0-beta.23302.3 6.0.0-preview.1.102 @@ -105,12 +105,12 @@ 6.0.0 8.0.0-preview.5.23279.2 - 14.0.0-alpha.1.23273.3 - 14.0.0-alpha.1.23273.3 - 14.0.0-alpha.1.23273.3 - 14.0.0-alpha.1.23273.3 - 14.0.0-alpha.1.23273.3 - 14.0.0-alpha.1.23273.3 + 14.0.0-alpha.1.23301.2 + 14.0.0-alpha.1.23301.2 + 14.0.0-alpha.1.23301.2 + 14.0.0-alpha.1.23301.2 + 14.0.0-alpha.1.23301.2 + 14.0.0-alpha.1.23301.2 1.0.0-alpha.1.23106.1 1.0.0-alpha.1.23106.1 @@ -139,27 +139,27 @@ 4.5.0 8.0.0-preview.5.23279.2 - 8.0.0-beta.23273.1 - 8.0.0-beta.23273.1 - 8.0.0-beta.23273.1 - 8.0.0-beta.23273.1 - 8.0.0-beta.23273.1 - 8.0.0-beta.23273.1 - 8.0.0-beta.23273.1 - 8.0.0-beta.23273.1 - 8.0.0-beta.23273.1 - 8.0.0-beta.23273.1 - 8.0.0-beta.23273.1 - 8.0.0-beta.23273.1 - 8.0.0-beta.23273.1 - 8.0.0-beta.23273.1 + 8.0.0-beta.23280.1 + 8.0.0-beta.23280.1 + 8.0.0-beta.23280.1 + 8.0.0-beta.23280.1 + 8.0.0-beta.23280.1 + 8.0.0-beta.23280.1 + 8.0.0-beta.23280.1 + 8.0.0-beta.23280.1 + 8.0.0-beta.23280.1 + 8.0.0-beta.23280.1 + 8.0.0-beta.23280.1 + 8.0.0-beta.23280.1 + 8.0.0-beta.23280.1 + 8.0.0-beta.23280.1 - 1.0.0-prerelease.23272.4 - 1.0.0-prerelease.23272.4 - 1.0.0-prerelease.23272.4 - 1.0.0-prerelease.23272.4 - 1.0.0-prerelease.23272.4 - 1.0.0-prerelease.23272.4 + 1.0.0-prerelease.23303.6 + 1.0.0-prerelease.23303.6 + 1.0.0-prerelease.23303.6 + 1.0.0-prerelease.23303.6 + 1.0.0-prerelease.23303.6 + 1.0.0-prerelease.23303.6 16.11.23-beta1.23063.1 2.0.0-beta4.22564.1 @@ -179,10 +179,10 @@ 1.1.0 17.4.0-preview-20220707-01 - 8.0.0-prerelease.23272.1 - 8.0.0-prerelease.23272.1 - 8.0.0-prerelease.23272.1 - 8.0.0-alpha.0.23272.2 + 8.0.0-prerelease.23279.1 + 8.0.0-prerelease.23279.1 + 8.0.0-prerelease.23279.1 + 8.0.0-alpha.0.23280.2 2.4.2 1.0.0 2.4.5 @@ -211,39 +211,39 @@ 8.0.0-preview.5.23279.2 - 0.11.4-alpha.23265.2 + 0.11.4-alpha.23301.1 - 8.0.0-preview.4.23177.3 + 8.0.0-preview.6.23280.1 2.1.7 8.0.0-alpha.1.23180.2 - 14.0.0-alpha.1.23273.3 - 14.0.0-alpha.1.23273.3 - 14.0.0-alpha.1.23273.3 - 14.0.0-alpha.1.23273.3 - 14.0.0-alpha.1.23273.3 - 14.0.0-alpha.1.23273.3 - 14.0.0-alpha.1.23273.3 - 14.0.0-alpha.1.23273.3 - 14.0.0-alpha.1.23273.3 - 14.0.0-alpha.1.23273.3 + 14.0.0-alpha.1.23301.2 + 14.0.0-alpha.1.23301.2 + 14.0.0-alpha.1.23301.2 + 14.0.0-alpha.1.23301.2 + 14.0.0-alpha.1.23301.2 + 14.0.0-alpha.1.23301.2 + 14.0.0-alpha.1.23301.2 + 14.0.0-alpha.1.23301.2 + 14.0.0-alpha.1.23301.2 + 14.0.0-alpha.1.23301.2 - 8.0.0-preview.6.23277.2 + 8.0.0-preview.6.23301.1 $(MicrosoftNETWorkloadEmscriptenCurrentManifest80100TransportVersion) 1.1.87-gba258badda 1.0.0-v3.14.0.5722 - 14.0.0-alpha.1.23273.3 - 14.0.0-alpha.1.23273.3 - 14.0.0-alpha.1.23273.3 - 14.0.0-alpha.1.23273.3 - 14.0.0-alpha.1.23273.3 - 14.0.0-alpha.1.23273.3 + 14.0.0-alpha.1.23301.2 + 14.0.0-alpha.1.23301.2 + 14.0.0-alpha.1.23301.2 + 14.0.0-alpha.1.23301.2 + 14.0.0-alpha.1.23301.2 + 14.0.0-alpha.1.23301.2 1.0.0-alpha.1.23106.1 1.0.0-alpha.1.23106.1 diff --git a/eng/common/sdk-task.ps1 b/eng/common/sdk-task.ps1 index e10a5968797463..6c4ac6fec1a99a 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.4.1" -MemberType NoteProperty + $GlobalJson.tools | Add-Member -Name "xcopy-msbuild" -Value "17.6.0-2" -MemberType NoteProperty } if ($GlobalJson.tools."xcopy-msbuild".Trim() -ine "none") { $xcopyMSBuildToolsFolder = InitializeXCopyMSBuild $GlobalJson.tools."xcopy-msbuild" -install $true diff --git a/eng/common/templates/job/job.yml b/eng/common/templates/job/job.yml index 44ad26abf54ba2..e20ee3a983cb05 100644 --- a/eng/common/templates/job/job.yml +++ b/eng/common/templates/job/job.yml @@ -75,6 +75,10 @@ jobs: - ${{ 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: @@ -83,7 +87,7 @@ jobs: - ${{ if ne(variable.name, '') }}: - name: ${{ variable.name }} value: ${{ variable.value }} - + # handle variable groups - ${{ if ne(variable.group, '') }}: - group: ${{ variable.group }} @@ -169,7 +173,7 @@ jobs: - ${{ 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 + displayName: Execute Microbuild cleanup tasks condition: and(always(), in(variables['_SignType'], 'real', 'test'), eq(variables['Agent.Os'], 'Windows_NT')) continueOnError: ${{ parameters.continueOnError }} env: @@ -219,7 +223,7 @@ jobs: displayName: Publish XUnit Test Results inputs: testResultsFormat: 'xUnit' - testResultsFiles: '*.xml' + testResultsFiles: '*.xml' searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-xunit mergeTestResults: ${{ parameters.mergeTestResults }} @@ -230,7 +234,7 @@ jobs: displayName: Publish TRX Test Results inputs: testResultsFormat: 'VSTest' - testResultsFiles: '*.trx' + testResultsFiles: '*.trx' searchFolder: '$(Build.SourcesDirectory)/artifacts/TestResults/$(_BuildConfig)' testRunTitle: ${{ coalesce(parameters.testRunTitle, parameters.name, '$(System.JobName)') }}-trx mergeTestResults: ${{ parameters.mergeTestResults }} diff --git a/eng/common/templates/steps/source-build.yml b/eng/common/templates/steps/source-build.yml index a97a185a367a92..1100521834a943 100644 --- a/eng/common/templates/steps/source-build.yml +++ b/eng/common/templates/steps/source-build.yml @@ -68,6 +68,11 @@ steps: 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' @@ -86,6 +91,7 @@ steps: $internalRestoreArgs \ $targetRidArgs \ $runtimeOsArgs \ + $baseOsArgs \ /p:SourceBuildNonPortable=${{ parameters.platform.nonPortable }} \ /p:ArcadeBuildFromSource=true \ /p:AssetManifestFileName=$assetManifestFileName diff --git a/eng/common/tools.ps1 b/eng/common/tools.ps1 index 38cf94ff88c6f3..ffe0b4e2dfc4d7 100644 --- a/eng/common/tools.ps1 +++ b/eng/common/tools.ps1 @@ -384,8 +384,8 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements = # If the version of msbuild is going to be xcopied, # use this version. Version matches a package here: - # https://dev.azure.com/dnceng/public/_packaging?_a=package&feed=dotnet-eng&package=RoslynTools.MSBuild&protocolType=NuGet&version=17.4.1&view=overview - $defaultXCopyMSBuildVersion = '17.4.1' + # https://dev.azure.com/dnceng/public/_artifacts/feed/dotnet-eng/NuGet/RoslynTools.MSBuild/versions/17.6.0-2 + $defaultXCopyMSBuildVersion = '17.6.0-2' if (!$vsRequirements) { if (Get-Member -InputObject $GlobalJson.tools -Name 'vs') { diff --git a/eng/packaging.targets b/eng/packaging.targets index 29291f1c6e6816..3e5f6a9e582865 100644 --- a/eng/packaging.targets +++ b/eng/packaging.targets @@ -16,6 +16,8 @@ false true + + true $(MSBuildThisFileDirectory)useSharedDesignerContext.txt PACKAGE.md diff --git a/eng/pipelines/common/evaluate-default-paths.yml b/eng/pipelines/common/evaluate-default-paths.yml index 70be16e61bad4b..8527d6ae77aaa8 100644 --- a/eng/pipelines/common/evaluate-default-paths.yml +++ b/eng/pipelines/common/evaluate-default-paths.yml @@ -17,7 +17,9 @@ parameters: src/libraries/sendtohelix-wasi.targets src/mono/mono/**/*wasm* src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/* + src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk/* src/mono/nuget/Microsoft.NET.Runtime.wasm.Sample.Mono/* + src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/* src/mono/nuget/Microsoft.NETCore.BrowserDebugHost.Transport/* src/mono/nuget/Microsoft.NET.Workload* src/mono/sample/wasm/* @@ -27,6 +29,7 @@ parameters: src/tasks/WasmAppBuilder/* src/tasks/WasmBuildTasks/* src/tasks/WorkloadBuildTasks/* + src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/* src/tests/Common/wasm-test-runner/* ] _wasm_pipelines: [ @@ -185,6 +188,8 @@ jobs: - src/mono/nuget/Microsoft.NET.Runtime.MonoAOTCompiler.Task/* - src/mono/nuget/Microsoft.NET.Runtime.MonoTargets.Sdk/* - src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Sdk/* + - src/mono/nuget/Microsoft.NET.Runtime.WebAssembly.Wasi.Sdk/* + - src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/* - src/mono/nuget/Microsoft.NET.Runtime.wasm.Sample.Mono/* - src/mono/nuget/Microsoft.NET.Workload* - src/mono/nuget/Microsoft.NETCore.BrowserDebugHost.Transport/* @@ -248,6 +253,7 @@ jobs: - src/mono/wasm/debugger/* - src/mono/wasm/Wasm.Build.Tests/* - src/mono/nuget/Microsoft.NET.Runtime* + src/mono/nuget/Microsoft.NET.Sdk.WebAssembly.Pack/* - src/mono/nuget/Microsoft.NET.Workload* - src/mono/nuget/Microsoft.NETCore.BrowserDebugHost.Transport/* - ${{ parameters._const_paths._always_exclude }} diff --git a/eng/pipelines/common/global-build-job.yml b/eng/pipelines/common/global-build-job.yml index 12f72b0d9e265f..cf93d34062b7da 100644 --- a/eng/pipelines/common/global-build-job.yml +++ b/eng/pipelines/common/global-build-job.yml @@ -162,6 +162,7 @@ jobs: - template: /eng/common/templates/steps/source-build.yml parameters: platform: + baseOS: ${{ parameters.baseOS }} buildScript: $(Build.SourcesDirectory)$(dir)build$(scriptExt) nonPortable: ${{ parameters.isNonPortableSourceBuild }} targetRID: ${{ parameters.targetRid }} diff --git a/eng/pipelines/common/platform-matrix.yml b/eng/pipelines/common/platform-matrix.yml index 4f0d6bfd5aeb3c..bae79645c0c6dc 100644 --- a/eng/pipelines/common/platform-matrix.yml +++ b/eng/pipelines/common/platform-matrix.yml @@ -307,6 +307,7 @@ jobs: 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. jobParameters: runtimeFlavor: ${{ parameters.runtimeFlavor }} + baseOS: linux buildConfig: ${{ parameters.buildConfig }} helixQueueGroup: ${{ parameters.helixQueueGroup }} isSourceBuild: true @@ -579,6 +580,26 @@ jobs: helixQueueGroup: ${{ parameters.helixQueueGroup }} ${{ insert }}: ${{ parameters.jobParameters }} +# Android x64 with Docker-in-Docker + +- ${{ if containsValue(parameters.platforms, 'android_x64_docker') }}: + - template: xplat-setup.yml + parameters: + jobTemplate: ${{ parameters.jobTemplate }} + helixQueuesTemplate: ${{ parameters.helixQueuesTemplate }} + variables: ${{ parameters.variables }} + osGroup: android + archType: x64 + targetRid: android-x64 + platform: android_x64 + shouldContinueOnError: ${{ parameters.shouldContinueOnError }} + container: android_docker + jobParameters: + runtimeFlavor: mono + buildConfig: ${{ parameters.buildConfig }} + helixQueueGroup: ${{ parameters.helixQueueGroup }} + ${{ insert }}: ${{ parameters.jobParameters }} + # Android x86 - ${{ if containsValue(parameters.platforms, 'android_x86') }}: diff --git a/eng/pipelines/common/templates/pipeline-with-resources.yml b/eng/pipelines/common/templates/pipeline-with-resources.yml index 9d3815ec3ded11..e135269d9e571a 100644 --- a/eng/pipelines/common/templates/pipeline-with-resources.yml +++ b/eng/pipelines/common/templates/pipeline-with-resources.yml @@ -33,10 +33,14 @@ resources: image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-arm64-alpine env: ROOTFS_DIR: /crossrootfs/arm64 - # This container contains all required toolsets to build for Android and for Linux with bionic libc. + # This container contains all required toolsets to build for Android and for Linux with bionic libc. - container: linux_bionic - image: mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-android + image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-android + + # This container contains all required toolsets to build for Android as well as tooling to build docker images. + - container: android_docker + image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-android-docker - container: linux_x64 image: mcr.microsoft.com/dotnet-buildtools/prereqs:cbl-mariner-2.0-cross-amd64 diff --git a/eng/pipelines/coreclr/perf-non-wasm-jobs.yml b/eng/pipelines/coreclr/perf-non-wasm-jobs.yml index cd8f01bf1652c2..3d943fce71b44f 100644 --- a/eng/pipelines/coreclr/perf-non-wasm-jobs.yml +++ b/eng/pipelines/coreclr/perf-non-wasm-jobs.yml @@ -102,6 +102,27 @@ jobs: archiveType: tar tarCompression: gz + # build NativeAOT iOS scenarios + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/common/global-build-job.yml + buildConfig: release + runtimeFlavor: mono + platforms: + - ios_arm64 + jobParameters: + nameSuffix: iOSNativeAOT + isOfficialBuild: false + extraStepsTemplate: /eng/pipelines/coreclr/templates/build-perf-sample-apps.yml + extraStepsParameters: + rootFolder: '$(Build.SourcesDirectory)/artifacts/' + includeRootFolder: true + displayName: iOS NativeAOT Artifacts + artifactName: iOSNativeAOTarm64 + archiveExtension: '.tar.gz' + archiveType: tar + tarCompression: gz + # build mono - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -143,6 +164,24 @@ jobs: runJobTemplate: /eng/pipelines/coreclr/templates/run-scenarios-job.yml logicalmachine: 'perfiphone12mini' iOSLlvmBuild: False + iOSStripSymbols: False + + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml + buildConfig: release + runtimeFlavor: mono + platforms: + - osx_x64 + jobParameters: + testGroup: perf + runtimeType: iOSMono + projectFile: ios_scenarios.proj + runKind: ios_scenarios + runJobTemplate: /eng/pipelines/coreclr/templates/run-scenarios-job.yml + logicalmachine: 'perfiphone12mini' + iOSLlvmBuild: False + iOSStripSymbols: True - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -159,6 +198,57 @@ jobs: runJobTemplate: /eng/pipelines/coreclr/templates/run-scenarios-job.yml logicalmachine: 'perfiphone12mini' iOSLlvmBuild: True + iOSStripSymbols: False + + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml + buildConfig: release + runtimeFlavor: mono + platforms: + - osx_x64 + jobParameters: + testGroup: perf + runtimeType: iOSMono + projectFile: ios_scenarios.proj + runKind: ios_scenarios + runJobTemplate: /eng/pipelines/coreclr/templates/run-scenarios-job.yml + logicalmachine: 'perfiphone12mini' + iOSLlvmBuild: True + iOSStripSymbols: True + + # run NativeAOT iOS scenarios + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml + buildConfig: release + runtimeFlavor: mono + platforms: + - osx_x64 + jobParameters: + testGroup: perf + runtimeType: iOSNativeAOT + projectFile: ios_scenarios.proj + runKind: ios_scenarios + runJobTemplate: /eng/pipelines/coreclr/templates/run-scenarios-job.yml + logicalmachine: 'perfiphone12mini' + iOSStripSymbols: False + + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml + buildConfig: release + runtimeFlavor: mono + platforms: + - osx_x64 + jobParameters: + testGroup: perf + runtimeType: iOSNativeAOT + projectFile: ios_scenarios.proj + runKind: ios_scenarios + runJobTemplate: /eng/pipelines/coreclr/templates/run-scenarios-job.yml + logicalmachine: 'perfiphone12mini' + iOSStripSymbols: True # run mono microbenchmarks perf job - template: /eng/pipelines/common/platform-matrix.yml @@ -232,7 +322,7 @@ jobs: runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml logicalmachine: 'perftiger' - # run coreclr perftiger microbenchmarks pgo perf jobs + # run coreclr perftiger microbenchmarks no dynamic pgo perf jobs - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml @@ -247,23 +337,7 @@ jobs: runKind: micro runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml logicalmachine: 'perftiger' - pgoRunType: -NoPgo - - - template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml - buildConfig: release - runtimeFlavor: coreclr - platforms: - - windows_x64 - jobParameters: - testGroup: perf - liveLibrariesBuildConfig: Release - projectFile: microbenchmarks.proj - runKind: micro - runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml - logicalmachine: 'perftiger' - pgoRunType: -DynamicPgo + pgoRunType: -NoDynamicPGO - template: /eng/pipelines/common/platform-matrix.yml parameters: @@ -279,23 +353,7 @@ jobs: runKind: micro runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml logicalmachine: 'perftiger' - pgoRunType: --dynamicpgo - - - template: /eng/pipelines/common/platform-matrix.yml - parameters: - jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml - buildConfig: release - runtimeFlavor: coreclr - platforms: - - windows_x64 - jobParameters: - testGroup: perf - liveLibrariesBuildConfig: Release - projectFile: microbenchmarks.proj - runKind: micro - runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml - logicalmachine: 'perftiger' - pgoRunType: -FullPgo + pgoRunType: --nodynamicpgo # run coreclr perfowl microbenchmarks perf job - template: /eng/pipelines/common/platform-matrix.yml diff --git a/eng/pipelines/coreclr/perf-wasm-prepare-artifacts-steps.yml b/eng/pipelines/coreclr/perf-wasm-prepare-artifacts-steps.yml index 0502a534d36cef..3015f0d6cb1413 100644 --- a/eng/pipelines/coreclr/perf-wasm-prepare-artifacts-steps.yml +++ b/eng/pipelines/coreclr/perf-wasm-prepare-artifacts-steps.yml @@ -12,10 +12,11 @@ steps: displayName: "Install workload using artifacts" - script: >- - mkdir -p $(Build.SourcesDirectory)/artifacts/staging && + mkdir -p $(Build.SourcesDirectory)/artifacts/staging/built-nugets && cp -r $(Build.SourcesDirectory)/artifacts/bin/dotnet-latest $(Build.SourcesDirectory)/artifacts/staging && cp -r $(Build.SourcesDirectory)/artifacts/bin/microsoft.netcore.app.runtime.browser-wasm $(Build.SourcesDirectory)/artifacts/staging && - cp -r $(Build.SourcesDirectory)/artifacts/bin/microsoft.netcore.app.ref $(Build.SourcesDirectory)/artifacts/staging + cp -r $(Build.SourcesDirectory)/artifacts/bin/microsoft.netcore.app.ref $(Build.SourcesDirectory)/artifacts/staging && + cp -r $(Build.SourcesDirectory)/artifacts/packages/${{ parameters.configForBuild }}/Shipping/Microsoft.NET.Sdk.WebAssembly.Pack* $(Build.SourcesDirectory)/artifacts/staging/built-nugets displayName: "Prepare artifacts staging directory" - template: /eng/pipelines/common/upload-artifact-step.yml diff --git a/eng/pipelines/coreclr/perf_slow.yml b/eng/pipelines/coreclr/perf_slow.yml index 1a12f56abeaa2a..ceb84962217ecb 100644 --- a/eng/pipelines/coreclr/perf_slow.yml +++ b/eng/pipelines/coreclr/perf_slow.yml @@ -189,7 +189,7 @@ extends: logicalmachine: 'perfampere' timeoutInMinutes: 780 - # run coreclr Linux arm64 ampere microbenchmarks perf job + # run coreclr Linux arm64 ampere no dynamic pgo microbenchmarks perf job - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml @@ -205,7 +205,7 @@ extends: runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml logicalmachine: 'perfampere' timeoutInMinutes: 780 - pgoRunType: --dynamicpgo + pgoRunType: --nodynamicpgo # run coreclr Windows arm64 microbenchmarks perf job - template: /eng/pipelines/common/platform-matrix.yml @@ -240,7 +240,7 @@ extends: logicalmachine: 'perfampere' timeoutInMinutes: 500 - # run coreclr Windows arm64 ampere dynamic Pgo microbenchmarks perf job + # run coreclr Windows arm64 ampere no dynamic pgo microbenchmarks perf job - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/coreclr/templates/perf-job.yml @@ -255,7 +255,7 @@ extends: runKind: micro runJobTemplate: /eng/pipelines/coreclr/templates/run-performance-job.yml logicalmachine: 'perfampere' - pgoRunType: -DynamicPgo + pgoRunType: -NoDynamicPGO timeoutInMinutes: 500 # run coreclr cloudvm microbenchmarks perf job diff --git a/eng/pipelines/coreclr/superpmi-collect.yml b/eng/pipelines/coreclr/superpmi-collect.yml index 453a4a2e1a8db3..4c66b20aecbc76 100644 --- a/eng/pipelines/coreclr/superpmi-collect.yml +++ b/eng/pipelines/coreclr/superpmi-collect.yml @@ -133,6 +133,26 @@ extends: collectionType: crossgen2 collectionName: libraries + - template: /eng/pipelines/common/platform-matrix.yml + parameters: + jobTemplate: /eng/pipelines/coreclr/templates/superpmi-collect-job.yml + buildConfig: checked + platforms: + - osx_arm64 + - linux_arm + - linux_arm64 + - linux_x64 + - windows_x64 + - windows_x86 + - windows_arm64 + helixQueueGroup: ci + helixQueuesTemplate: /eng/pipelines/coreclr/templates/helix-queues-setup.yml + jobParameters: + testGroup: outerloop + liveLibrariesBuildConfig: Release + collectionType: run + collectionName: realworld + - template: /eng/pipelines/common/platform-matrix.yml parameters: jobTemplate: /eng/pipelines/coreclr/templates/superpmi-collect-job.yml diff --git a/eng/pipelines/coreclr/templates/build-perf-sample-apps.yml b/eng/pipelines/coreclr/templates/build-perf-sample-apps.yml index bdc0475fb5da84..89604f865c4ae8 100644 --- a/eng/pipelines/coreclr/templates/build-perf-sample-apps.yml +++ b/eng/pipelines/coreclr/templates/build-perf-sample-apps.yml @@ -35,13 +35,13 @@ steps: - script: rm -r -f $(Build.SourcesDirectory)/artifacts/bin/AndroidSampleApp workingDirectory: $(Build.SourcesDirectory)/artifacts/bin displayName: clean bindir - - - ${{ if eq(parameters.osGroup, 'ios') }}: - - script: make build-appbundle TARGET=ios MONO_ARCH=arm64 MONO_CONFIG=Release AOT=True USE_LLVM=False DEPLOY_AND_RUN=false + + - ${{ if and(eq(parameters.osGroup, 'ios'), eq(parameters.nameSuffix, 'iOSMono')) }}: + - script: make build-appbundle TARGET=ios MONO_ARCH=arm64 MONO_CONFIG=Release AOT=True USE_LLVM=False DEPLOY_AND_RUN=false STRIP_DEBUG_SYMBOLS=false env: DevTeamProvisioning: '-' workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS - displayName: Build HelloiOS AOT sample app LLVM=False + displayName: Build HelloiOS AOT sample app LLVM=False STRIP_SYMBOLS=False - task: PublishBuildArtifacts@1 condition: succeededOrFailed() displayName: 'Publish binlog' @@ -53,17 +53,39 @@ steps: rootFolder: $(Build.SourcesDirectory)/src/mono/sample/iOS/bin/ios-arm64/publish/app/HelloiOS/Release-iphoneos/HelloiOS.app includeRootFolder: true displayName: iOS Sample App NoLLVM - artifactName: iOSSampleAppNoLLVM + artifactName: iOSSampleAppNoLLVMSymbols archiveExtension: '.zip' archiveType: zip - script: rm -r -f $(Build.SourcesDirectory)/src/mono/sample/iOS/bin workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS displayName: Clean bindir - - script: make build-appbundle TARGET=ios MONO_ARCH=arm64 MONO_CONFIG=Release AOT=True USE_LLVM=True DEPLOY_AND_RUN=false + - script: make build-appbundle TARGET=ios MONO_ARCH=arm64 MONO_CONFIG=Release AOT=True USE_LLVM=False DEPLOY_AND_RUN=false STRIP_DEBUG_SYMBOLS=true env: DevTeamProvisioning: '-' workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS - displayName: Build HelloiOS AOT sample app LLVM=True + displayName: Build HelloiOS AOT sample app LLVM=False STRIP_SYMBOLS=True + - task: PublishBuildArtifacts@1 + condition: succeededOrFailed() + displayName: 'Publish binlog' + inputs: + pathtoPublish: $(Build.SourcesDirectory)/src/mono/sample/iOS/msbuild.binlog + artifactName: ${{ parameters.artifactName }} + - template: /eng/pipelines/common/upload-artifact-step.yml + parameters: + rootFolder: $(Build.SourcesDirectory)/src/mono/sample/iOS/bin/ios-arm64/publish/app/HelloiOS/Release-iphoneos/HelloiOS.app + includeRootFolder: true + displayName: iOS Sample App NoLLVM NoSymbols + artifactName: iOSSampleAppNoLLVMNoSymbols + archiveExtension: '.zip' + archiveType: zip + - script: rm -r -f $(Build.SourcesDirectory)/src/mono/sample/iOS/bin + workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS + displayName: Clean bindir + - script: make build-appbundle TARGET=ios MONO_ARCH=arm64 MONO_CONFIG=Release AOT=True USE_LLVM=True DEPLOY_AND_RUN=false STRIP_DEBUG_SYMBOLS=false + env: + DevTeamProvisioning: '-' + workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS + displayName: Build HelloiOS AOT sample app LLVM=True STRIP_SYMBOLS=False - task: PublishBuildArtifacts@1 condition: succeededOrFailed() displayName: 'Publish binlog' @@ -75,6 +97,71 @@ steps: rootFolder: $(Build.SourcesDirectory)/src/mono/sample/iOS/bin/ios-arm64/publish/app/HelloiOS/Release-iphoneos/HelloiOS.app includeRootFolder: true displayName: iOS Sample App LLVM - artifactName: iOSSampleAppLLVM + artifactName: iOSSampleAppLLVMSymbols + archiveExtension: '.zip' + archiveType: zip + - script: rm -r -f $(Build.SourcesDirectory)/src/mono/sample/iOS/bin + workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS + displayName: Clean bindir + - script: make build-appbundle TARGET=ios MONO_ARCH=arm64 MONO_CONFIG=Release AOT=True USE_LLVM=True DEPLOY_AND_RUN=false STRIP_DEBUG_SYMBOLS=true + env: + DevTeamProvisioning: '-' + workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS + displayName: Build HelloiOS AOT sample app LLVM=True STRIP_SYMBOLS=True + - task: PublishBuildArtifacts@1 + condition: succeededOrFailed() + displayName: 'Publish binlog' + inputs: + pathtoPublish: $(Build.SourcesDirectory)/src/mono/sample/iOS/msbuild.binlog + artifactName: ${{ parameters.artifactName }} + - template: /eng/pipelines/common/upload-artifact-step.yml + parameters: + rootFolder: $(Build.SourcesDirectory)/src/mono/sample/iOS/bin/ios-arm64/publish/app/HelloiOS/Release-iphoneos/HelloiOS.app + includeRootFolder: true + displayName: iOS Sample App LLVM NoSymbols + artifactName: iOSSampleAppLLVMNoSymbols archiveExtension: '.zip' archiveType: zip + + - ${{ if and(eq(parameters.osGroup, 'ios'), eq(parameters.nameSuffix, 'iOSNativeAOT')) }}: + - script: make world TARGET_OS=ios TARGET_ARCH=arm64 BUILD_CONFIG=Release DEPLOY_AND_RUN=false STRIP_DEBUG_SYMBOLS=false + env: + DevTeamProvisioning: '-' + workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS-NativeAOT + displayName: Build HelloiOS Native AOT sample app STRIP_SYMBOLS=False + - task: PublishBuildArtifacts@1 + condition: succeededOrFailed() + displayName: 'Publish binlog' + inputs: + pathtoPublish: $(Build.SourcesDirectory)/src/mono/sample/iOS-NativeAOT/msbuild.binlog + artifactName: ${{ parameters.artifactName }} + - template: /eng/pipelines/common/upload-artifact-step.yml + parameters: + rootFolder: $(Build.SourcesDirectory)/src/mono/sample/iOS-NativeAOT/bin/publish/app/HelloiOS/Release-iphoneos/HelloiOS.app + includeRootFolder: true + displayName: iOS Sample App Symbols + artifactName: iOSSampleAppSymbols + archiveExtension: '.zip' + archiveType: zip + - script: rm -r -f $(Build.SourcesDirectory)/src/mono/sample/iOS-NativeAOT/bin + workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS-NativeAOT + displayName: Clean bindir + - script: make world TARGET_OS=ios TARGET_ARCH=arm64 BUILD_CONFIG=Release DEPLOY_AND_RUN=false STRIP_DEBUG_SYMBOLS=true + env: + DevTeamProvisioning: '-' + workingDirectory: $(Build.SourcesDirectory)/src/mono/sample/iOS-NativeAOT + displayName: Build HelloiOS Native AOT sample app STRIP_SYMBOLS=True + - task: PublishBuildArtifacts@1 + condition: succeededOrFailed() + displayName: 'Publish binlog' + inputs: + pathtoPublish: $(Build.SourcesDirectory)/src/mono/sample/iOS-NativeAOT/msbuild.binlog + artifactName: ${{ parameters.artifactName }} + - template: /eng/pipelines/common/upload-artifact-step.yml + parameters: + rootFolder: $(Build.SourcesDirectory)/src/mono/sample/iOS-NativeAOT/bin/publish/app/HelloiOS/Release-iphoneos/HelloiOS.app + includeRootFolder: true + displayName: iOS Sample App NoSymbols + artifactName: iOSSampleAppNoSymbols + archiveExtension: '.zip' + archiveType: zip \ No newline at end of file diff --git a/eng/pipelines/coreclr/templates/perf-job.yml b/eng/pipelines/coreclr/templates/perf-job.yml index e61e6761a89d7f..56766c72187365 100644 --- a/eng/pipelines/coreclr/templates/perf-job.yml +++ b/eng/pipelines/coreclr/templates/perf-job.yml @@ -19,6 +19,7 @@ parameters: pgoRunType: '' javascriptEngine: 'NoJS' iOSLlvmBuild: 'False' + iOSStripSymbols: 'False' skipLiveLibrariesDownload: false collectHelixLogsScript: '' timeoutInMinutes: 320 @@ -37,8 +38,8 @@ jobs: - template: ${{ parameters.runJobTemplate }} parameters: # Compute job name from template parameters - jobName: ${{ format('perfbuild_{0}{1}_{2}_{3}_{4}_{5}_{6}_{7}_{8}_{9}_{10}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.runtimeType, parameters.codeGenType, parameters.runKind, parameters.logicalMachine, parameters.javascriptEngine, parameters.pgoRunType, parameters.iosLlvmBuild) }} - displayName: ${{ format('Performance {0}{1} {2} {3} {4} {5} {6} {7} {8} {9} {10}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.runtimeType, parameters.codeGenType, parameters.runKind, parameters.logicalMachine, parameters.javascriptEngine, parameters.pgoRunType, parameters.iosLlvmBuild) }} + jobName: ${{ format('perfbuild_{0}{1}_{2}_{3}_{4}_{5}_{6}_{7}_{8}_{9}_{10}_{11}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.runtimeType, parameters.codeGenType, parameters.runKind, parameters.logicalMachine, parameters.javascriptEngine, parameters.pgoRunType, parameters.iosLlvmBuild, parameters.iosStripSymbols) }} + displayName: ${{ format('Performance {0}{1} {2} {3} {4} {5} {6} {7} {8} {9} {10} {11}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig, parameters.runtimeType, parameters.codeGenType, parameters.runKind, parameters.logicalMachine, parameters.javascriptEngine, parameters.pgoRunType, parameters.iosLlvmBuild, parameters.iosStripSymbols) }} pool: ${{ parameters.pool }} buildConfig: ${{ parameters.buildConfig }} archType: ${{ parameters.archType }} @@ -56,6 +57,7 @@ jobs: pgoRunType: ${{ parameters.pgoRunType }} javascriptEngine: ${{ parameters.javascriptEngine }} iosLlvmBuild: ${{ parameters.iosLlvmBuild }} + iosStripSymbols: ${{ parameters.iosStripSymbols }} timeoutInMinutes: ${{ parameters.timeoutInMinutes }} ${{ if and(eq(parameters.runtimeType, 'wasm'), eq(parameters.codeGenType, 'aot')) }}: @@ -68,7 +70,7 @@ jobs: # Test job depends on the corresponding build job ${{ if eq(parameters.downloadSpecificBuild.buildId, '') }}: dependsOn: - - ${{ if not(in(parameters.runtimeType, 'AndroidMono', 'iOSMono', 'wasm')) }}: + - ${{ if not(in(parameters.runtimeType, 'AndroidMono', 'iOSMono', 'iOSNativeAOT', 'wasm')) }}: - ${{ format('coreclr_{0}_product_build_{1}{2}_{3}_{4}', parameters.runtimeVariant, parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.buildConfig) }} - ${{ if and(ne(parameters.liveLibrariesBuildConfig, ''), eq(parameters.skipLiveLibrariesDownload, 'false')) }}: - ${{ format('libraries_build_{0}{1}_{2}_{3}', parameters.osGroup, parameters.osSubgroup, parameters.archType, parameters.liveLibrariesBuildConfig) }} @@ -83,13 +85,15 @@ jobs: - ${{ 'Build_ios_arm64_release_PerfBDNApp' }} - ${{ if eq(parameters.runtimeType, 'iOSMono')}}: - ${{ 'build_ios_arm64_release_iOSMono' }} + - ${{ if eq(parameters.runtimeType, 'iOSNativeAOT')}}: + - ${{ 'build_ios_arm64_release_iOSNativeAOT' }} - ${{ if and(eq(parameters.osGroup, 'windows'), not(in(parameters.runtimeType, 'AndroidMono', 'iOSMono'))) }}: + ${{ if and(eq(parameters.osGroup, 'windows'), not(in(parameters.runtimeType, 'AndroidMono', 'iOSMono', 'iOSNativeAOT'))) }}: ${{ if eq(parameters.runtimeType, 'mono') }}: extraSetupParameters: -Architecture ${{ parameters.archType }} -MonoDotnet $(Build.SourcesDirectory)\.dotnet-mono ${{ if eq(parameters.runtimeType, 'coreclr') }}: extraSetupParameters: -CoreRootDirectory $(Build.SourcesDirectory)\artifacts\tests\coreclr\${{ parameters.osGroup }}.${{ parameters.archType }}.Release\Tests\Core_Root -Architecture ${{ parameters.archType }} - ${{ if and(ne(parameters.osGroup, 'windows'), not(in(parameters.runtimeType, 'AndroidMono', 'iOSMono'))) }}: + ${{ if and(ne(parameters.osGroup, 'windows'), not(in(parameters.runtimeType, 'AndroidMono', 'iOSMono', 'iOSNativeAOT'))) }}: ${{ if and(eq(parameters.runtimeType, 'mono'), ne(parameters.codeGenType, 'AOT')) }}: extraSetupParameters: --architecture ${{ parameters.archType }} --monodotnet $(Build.SourcesDirectory)/.dotnet-mono ${{ if and(eq(parameters.runtimeType, 'wasm'), ne(parameters.codeGenType, 'AOT')) }}: @@ -104,8 +108,10 @@ jobs: extraSetupParameters: --corerootdirectory $(Build.SourcesDirectory)/artifacts/tests/coreclr/${{ parameters.osGroup }}.${{ parameters.archType }}.Release/Tests/Core_Root --architecture ${{ parameters.archType }} --alpine ${{ if in(parameters.runtimeType, 'AndroidMono') }}: extraSetupParameters: -Architecture ${{ parameters.archType }} -AndroidMono - ${{ if in(parameters.runtimeType, 'iosMono') }}: - extraSetupParameters: --architecture ${{ parameters.archType }} --iosmono --iosllvmbuild ${{ parameters.iOSLlvmBuild }} + ${{ if in(parameters.runtimeType, 'iOSMono') }}: + extraSetupParameters: --architecture ${{ parameters.archType }} --iosmono --iosllvmbuild ${{ parameters.iOSLlvmBuild }} --iosstripsymbols ${{ parameters.iOSStripSymbols }} + ${{ if in(parameters.runtimeType, 'iOSNativeAOT') }}: + extraSetupParameters: --architecture ${{ parameters.archType }} --iosnativeaot --iosllvmbuild ${{ parameters.iOSLlvmBuild }} --iosstripsymbols ${{ parameters.iOSStripSymbols }} variables: - ${{ each variable in parameters.variables }}: @@ -147,7 +153,7 @@ jobs: displayName: 'live-built libraries' # Download coreclr - - ${{ if not(in(parameters.runtimeType, 'AndroidMono', 'iOSMono', 'wasm')) }}: + - ${{ if not(in(parameters.runtimeType, 'AndroidMono', 'iOSMono', 'iOSNativeAOT', 'wasm')) }}: - template: /eng/pipelines/common/download-artifact-step.yml parameters: unpackFolder: $(buildProductRootFolderPath) @@ -188,6 +194,7 @@ jobs: mkdir -p $(librariesDownloadDir)/bin/wasm/wasm-data && mkdir -p $(librariesDownloadDir)/bin/wasm/dotnet && cp -r $(librariesDownloadDir)/BrowserWasm/staging/dotnet-latest/* $(librariesDownloadDir)/bin/wasm/dotnet && + cp -r $(librariesDownloadDir)/BrowserWasm/staging/built-nugets $(librariesDownloadDir)/bin/wasm && cp src/mono/wasm/Wasm.Build.Tests/data/test-main-7.0.js $(librariesDownloadDir)/bin/wasm/wasm-data/test-main.js && find $(librariesDownloadDir)/bin/wasm -type d && find $(librariesDownloadDir)/bin/wasm -type f -exec chmod 664 {} \; @@ -222,39 +229,50 @@ jobs: artifactName: 'AndroidBDNApk' displayName: 'Mono Android BDN Apk' - # Download iOSMono tests - - ${{ if eq(parameters.runtimeType, 'iOSMono') }}: + # Download iOSMono and Native AOT tests + - ${{ if or(eq(parameters.runtimeType, 'iOSMono'), eq(parameters.runtimeType, 'iOSNativeAOT')) }}: - template: /eng/pipelines/common/download-artifact-step.yml parameters: - unpackFolder: $(Build.SourcesDirectory)/iosHelloWorld/nollvm + unpackFolder: $(Build.SourcesDirectory)/iosHelloWorld cleanUnpackFolder: false - artifactFileName: 'iOSSampleAppNoLLVM.zip' - artifactName: 'iOSSampleAppNoLLVM' - displayName: 'iOS Sample App NoLLVM' - - template: /eng/pipelines/common/download-artifact-step.yml - parameters: - unpackFolder: $(Build.SourcesDirectory)/iosHelloWorld/llvm - cleanUnpackFolder: false - artifactFileName: 'iOSSampleAppLLVM.zip' - artifactName: 'iOSSampleAppLLVM' - displayName: 'iOS Sample App LLVM' - # same artifact as above but don't extract .zip - - task: DownloadBuildArtifacts@0 - displayName: 'Download iOS Sample App NoLLVM' - inputs: - buildType: current - downloadType: single - downloadPath: '$(Build.SourcesDirectory)/iosHelloWorldZip/nollvmzip' - artifactName: 'iOSSampleAppNoLLVM' - checkDownloadedFiles: true + ${{ if and(eq(parameters.runtimeType, 'iOSMono'), eq(parameters.iOSLlvmBuild, 'False'), eq(parameters.iOSStripSymbols, 'False')) }}: + artifactName: 'iOSSampleAppNoLLVMSymbols' + artifactFileName: 'iOSSampleAppNoLLVMSymbols.zip' + ${{ if and(eq(parameters.runtimeType, 'iOSMono'), eq(parameters.iOSLlvmBuild, 'False'), eq(parameters.iOSStripSymbols, 'True')) }}: + artifactName: 'iOSSampleAppNoLLVMNoSymbols' + artifactFileName: 'iOSSampleAppNoLLVMNoSymbols.zip' + ${{ if and(eq(parameters.runtimeType, 'iOSMono'), eq(parameters.iOSLlvmBuild, 'True'), eq(parameters.iOSStripSymbols, 'False')) }}: + artifactName: 'iOSSampleAppLLVMSymbols' + artifactFileName: 'iOSSampleAppLLVMSymbols.zip' + ${{ if and(eq(parameters.runtimeType, 'iOSMono'), eq(parameters.iOSLlvmBuild, 'True'), eq(parameters.iOSStripSymbols, 'True')) }}: + artifactName: 'iOSSampleAppLLVMNoSymbols' + artifactFileName: 'iOSSampleAppLLVMNoSymbols.zip' + ${{ if and(eq(parameters.runtimeType, 'iOSNativeAOT'), eq(parameters.iOSStripSymbols, 'False')) }}: + artifactName: 'iOSSampleAppSymbols' + artifactFileName: 'iOSSampleAppSymbols.zip' + ${{ if and(eq(parameters.runtimeType, 'iOSNativeAOT'), eq(parameters.iOSStripSymbols, 'True')) }}: + artifactName: 'iOSSampleAppNoSymbols' + artifactFileName: 'iOSSampleAppNoSymbols.zip' + displayName: 'iOS Sample App' # same artifact as above but don't extract .zip - task: DownloadBuildArtifacts@0 - displayName: 'Download iOS Sample App LLVM' + displayName: 'Download iOS Sample App' inputs: buildType: current downloadType: single - downloadPath: '$(Build.SourcesDirectory)/iosHelloWorldZip/llvmzip' - artifactName: 'iOSSampleAppLLVM' + downloadPath: '$(Build.SourcesDirectory)/iosHelloWorldZip' + ${{ if and(eq(parameters.runtimeType, 'iOSMono'), eq(parameters.iOSLlvmBuild, 'False'), eq(parameters.iOSStripSymbols, 'False')) }}: + artifactName: 'iOSSampleAppNoLLVMSymbols' + ${{ if and(eq(parameters.runtimeType, 'iOSMono'), eq(parameters.iOSLlvmBuild, 'False'), eq(parameters.iOSStripSymbols, 'True')) }}: + artifactName: 'iOSSampleAppNoLLVMNoSymbols' + ${{ if and(eq(parameters.runtimeType, 'iOSMono'), eq(parameters.iOSLlvmBuild, 'True'), eq(parameters.iOSStripSymbols, 'False')) }}: + artifactName: 'iOSSampleAppLLVMSymbols' + ${{ if and(eq(parameters.runtimeType, 'iOSMono'), eq(parameters.iOSLlvmBuild, 'True'), eq(parameters.iOSStripSymbols, 'True')) }}: + artifactName: 'iOSSampleAppLLVMNoSymbols' + ${{ if and(eq(parameters.runtimeType, 'iOSNativeAOT'), eq(parameters.iOSStripSymbols, 'False')) }}: + artifactName: 'iOSSampleAppSymbols' + ${{ if and(eq(parameters.runtimeType, 'iOSNativeAOT'), eq(parameters.iOSStripSymbols, 'True')) }}: + artifactName: 'iOSSampleAppNoSymbols' checkDownloadedFiles: true # Create Core_Root @@ -265,8 +283,8 @@ jobs: # Copy the runtime directory into the testhost folder to include OOBs. - script: "build.cmd -subset libs.pretest -configuration release -ci -arch $(archType) -testscope innerloop /p:RuntimeArtifactsPath=$(librariesDownloadDir)\\bin\\mono\\$(osGroup).$(archType).$(buildConfigUpper) /p:RuntimeFlavor=mono;xcopy $(Build.SourcesDirectory)\\artifacts\\bin\\runtime\\net8.0-$(osGroup)-$(buildConfigUpper)-$(archType)\\* $(Build.SourcesDirectory)\\artifacts\\bin\\testhost\\net8.0-$(osGroup)-$(buildConfigUpper)-$(archType)\\shared\\Microsoft.NETCore.App\\$(productVersion) /E /I /Y;xcopy $(Build.SourcesDirectory)\\artifacts\\bin\\testhost\\net8.0-$(osGroup)-$(buildConfigUpper)-$(archType)\\* $(Build.SourcesDirectory)\\.dotnet-mono /E /I /Y;copy $(Build.SourcesDirectory)\\artifacts\\bin\\coreclr\\$(osGroup).$(archType).$(buildConfigUpper)\\corerun.exe $(Build.SourcesDirectory)\\.dotnet-mono\\shared\\Microsoft.NETCore.App\\$(productVersion)\\corerun.exe" displayName: "Create mono dotnet (Windows)" - condition: and(and(succeeded(), eq(variables.runtimeFlavorName, 'Mono')), eq(variables.osGroup, 'windows'), not(in('${{ parameters.runtimeType }}', 'AndroidMono', 'iOSMono'))) + condition: and(and(succeeded(), eq(variables.runtimeFlavorName, 'Mono')), eq(variables.osGroup, 'windows'), not(in('${{ parameters.runtimeType }}', 'AndroidMono', 'iOSMono', 'iOSNativeAOT'))) - script: "mkdir $(Build.SourcesDirectory)/.dotnet-mono;./build.sh -subset libs.pretest -configuration release -ci -arch $(archType) -testscope innerloop /p:RuntimeArtifactsPath=$(librariesDownloadDir)/bin/mono/$(osGroup).$(archType).$(buildConfigUpper) /p:RuntimeFlavor=mono;cp $(Build.SourcesDirectory)/artifacts/bin/runtime/net8.0-$(osGroup)-$(buildConfigUpper)-$(archType)/* $(Build.SourcesDirectory)/artifacts/bin/testhost/net8.0-$(osGroup)-$(buildConfigUpper)-$(archType)/shared/Microsoft.NETCore.App/$(productVersion) -rf;cp $(Build.SourcesDirectory)/artifacts/bin/testhost/net8.0-$(osGroup)-$(buildConfigUpper)-$(archType)/* $(Build.SourcesDirectory)/.dotnet-mono -r;cp $(Build.SourcesDirectory)/artifacts/bin/coreclr/$(osGroup).$(archType).$(buildConfigUpper)/corerun $(Build.SourcesDirectory)/.dotnet-mono/shared/Microsoft.NETCore.App/$(productVersion)/corerun" displayName: "Create mono dotnet (Linux)" - condition: and(and(succeeded(), eq(variables.runtimeFlavorName, 'Mono')), ne(variables.osGroup, 'windows'), not(in('${{ parameters.runtimeType }}', 'AndroidMono', 'iOSMono'))) + condition: and(and(succeeded(), eq(variables.runtimeFlavorName, 'Mono')), ne(variables.osGroup, 'windows'), not(in('${{ parameters.runtimeType }}', 'AndroidMono', 'iOSMono', 'iOSNativeAOT'))) diff --git a/eng/pipelines/coreclr/templates/run-scenarios-job.yml b/eng/pipelines/coreclr/templates/run-scenarios-job.yml index c8267446e516d8..ba6875b6a7fec3 100644 --- a/eng/pipelines/coreclr/templates/run-scenarios-job.yml +++ b/eng/pipelines/coreclr/templates/run-scenarios-job.yml @@ -142,6 +142,7 @@ jobs: - script: >- mkdir -p $(librariesDownloadDir)/bin/wasm/data && cp -r $(librariesDownloadDir)/BrowserWasm/staging/dotnet-latest $(librariesDownloadDir)/bin/wasm && + cp -r $(librariesDownloadDir)/BrowserWasm/staging/built-nugets $(librariesDownloadDir)/bin/wasm && cp src/mono/wasm/Wasm.Build.Tests/data/test-main-7.0.js $(librariesDownloadDir)/bin/wasm/data/test-main.js && find $(librariesDownloadDir)/bin/wasm -type f -exec chmod 664 {} \; displayName: "Create wasm directory (Linux)" @@ -215,6 +216,6 @@ jobs: displayName: Publish Logs inputs: targetPath: $(Build.SourcesDirectory)/artifacts/log - artifactName: 'Performance_Run_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)_${{ parameters.runtimeType }}_${{ parameters.codeGenType }}_${{ parameters.runKind }}_$(iOSLlvmBuild)' + artifactName: 'Performance_Run_$(osGroup)$(osSubgroup)_$(archType)_$(buildConfig)_${{ parameters.runtimeType }}_${{ parameters.codeGenType }}_${{ parameters.runKind }}_$(iOSLlvmBuild)_$(iOSStripSymbols)' continueOnError: true condition: always() diff --git a/eng/pipelines/coreclr/templates/run-superpmi-collect-job.yml b/eng/pipelines/coreclr/templates/run-superpmi-collect-job.yml index ef55089a230467..ab401a83f6959f 100644 --- a/eng/pipelines/coreclr/templates/run-superpmi-collect-job.yml +++ b/eng/pipelines/coreclr/templates/run-superpmi-collect-job.yml @@ -91,6 +91,9 @@ jobs: - ${{ if eq(parameters.collectionName, 'benchmarks') }}: - name: InputDirectory value: '$(Core_Root_Dir)' + - ${{ if eq(parameters.collectionName, 'realworld') }}: + - name: InputDirectory + value: '$(Core_Root_Dir)' - ${{ if eq(parameters.collectionName, 'coreclr_tests') }}: - name: InputDirectory value: '$(managedTestArtifactRootFolderPath)' diff --git a/eng/pipelines/runtime-android-grpc-client-tests.yml b/eng/pipelines/runtime-android-grpc-client-tests.yml index 2c52bbf136c78d..00e51f766d95ce 100644 --- a/eng/pipelines/runtime-android-grpc-client-tests.yml +++ b/eng/pipelines/runtime-android-grpc-client-tests.yml @@ -36,7 +36,7 @@ extends: buildConfig: Release runtimeFlavor: mono platforms: - - android_x64 + - android_x64_docker jobParameters: testGroup: innerloop nameSuffix: AllSubsets_Mono_gRPC diff --git a/eng/pipelines/runtime-codeql.yml b/eng/pipelines/runtime-codeql.yml index 62c002926b70da..34fa555d180fe6 100644 --- a/eng/pipelines/runtime-codeql.yml +++ b/eng/pipelines/runtime-codeql.yml @@ -2,8 +2,13 @@ trigger: none schedules: - - cron: 0 12 * * 1 - displayName: Weekly Monday CodeQL/Semmle run + - cron: 0 12 * * 1,4,6 + # CodeQL auto-injects into other pipelines and will do a scan if one hasn't + # been done in 72 hours. These can cause timeouts, so we ensure that one has + # already been performed. We can increase this to 4x/week or be more + # sophisticated if the 72 hour period ending Thursday ("4" in the cron line) + # causes a problem. + displayName: 3x/week CodeQL/Semmle run branches: include: - main diff --git a/eng/pipelines/runtime.yml b/eng/pipelines/runtime.yml index 23fbbff0770c5c..4b182fb0e7be2a 100644 --- a/eng/pipelines/runtime.yml +++ b/eng/pipelines/runtime.yml @@ -248,7 +248,7 @@ extends: extraStepsTemplate: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml extraStepsParameters: creator: dotnet-bot - testBuildArgs: 'nativeaot tree ";nativeaot;Loader;Interop;tracing/eventpipe/config;tracing/eventpipe/simpleprovidervalidation;" test tracing/eventcounter/runtimecounters.csproj /p:BuildNativeAotFrameworkObjects=true' + testBuildArgs: 'nativeaot tree ";nativeaot;Loader;Interop;tracing/eventpipe/config;tracing/eventpipe/diagnosticport;tracing/eventpipe/reverse;" test tracing/eventcounter/runtimecounters.csproj /p:BuildNativeAotFrameworkObjects=true' liveLibrariesBuildConfig: Release testRunNamePrefixSuffix: NativeAOT_$(_BuildConfig) extraVariablesTemplates: @@ -290,7 +290,7 @@ extends: extraStepsTemplate: /eng/pipelines/coreclr/nativeaot-post-build-steps.yml extraStepsParameters: creator: dotnet-bot - testBuildArgs: nativeaot tree nativeaot + testBuildArgs: 'nativeaot tree ";nativeaot;tracing/eventpipe/simpleprovidervalidation;"' liveLibrariesBuildConfig: Release testRunNamePrefixSuffix: NativeAOT_$(_BuildConfig) extraVariablesTemplates: diff --git a/eng/resolveContract.targets b/eng/resolveContract.targets index 2dc517aaa96171..6d414f46f93e6b 100644 --- a/eng/resolveContract.targets +++ b/eng/resolveContract.targets @@ -1,4 +1,5 @@ + + + true + true + + false diff --git a/eng/targetingpacks.targets b/eng/targetingpacks.targets index ebdebf46c8b678..14ceef19b704da 100644 --- a/eng/targetingpacks.targets +++ b/eng/targetingpacks.targets @@ -35,7 +35,7 @@ LatestRuntimeFrameworkVersion="$(ProductVersion)" RuntimeFrameworkName="$(LocalFrameworkOverrideName)" RuntimePackNamePatterns="$(LocalFrameworkOverrideName).Runtime.**RID**" - RuntimePackRuntimeIdentifiers="linux-arm;linux-arm64;linux-musl-arm64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;tizen.4.0.0-armel;tizen.5.0.0-armel;win-arm;win-arm64;win-x64;win-x86;linux-musl-arm;osx-arm64;maccatalyst-x64;maccatalyst-arm64;linux-s390x;linux-bionic-arm;linux-bionic-arm64;linux-bionic-x64;linux-bionic-x86" + RuntimePackRuntimeIdentifiers="linux-arm;linux-arm64;linux-musl-arm64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;tizen.4.0.0-armel;tizen.5.0.0-armel;win-arm64;win-x64;win-x86;linux-musl-arm;osx-arm64;maccatalyst-x64;maccatalyst-arm64;linux-s390x;linux-bionic-arm;linux-bionic-arm64;linux-bionic-x64;linux-bionic-x86" TargetFramework="$(NetCoreAppCurrent)" TargetingPackName="$(LocalFrameworkOverrideName).Ref" TargetingPackVersion="$(ProductVersion)" @@ -45,20 +45,20 @@ RuntimeFrameworkName="$(LocalFrameworkOverrideName)" LatestRuntimeFrameworkVersion="$(ProductVersion)" RuntimePackNamePatterns="$(LocalFrameworkOverrideName).Runtime.Mono.**RID**" - RuntimePackRuntimeIdentifiers="linux-arm;linux-arm64;linux-musl-arm64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;win-arm;win-arm64;win-x64;win-x86;linux-musl-arm;osx-arm64;maccatalyst-x64;maccatalyst-arm64;linux-s390x;linux-bionic-arm;linux-bionic-arm64;linux-bionic-x64;linux-bionic-x86;browser-wasm;wasi-wasm;ios-arm64;iossimulator-arm64;iossimulator-x64;tvos-arm64;tvossimulator-arm64;tvossimulator-x64;android-arm64;android-arm;android-x64;android-x86" + RuntimePackRuntimeIdentifiers="linux-arm;linux-arm64;linux-musl-arm64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;win-arm64;win-x64;win-x86;linux-musl-arm;osx-arm64;maccatalyst-x64;maccatalyst-arm64;linux-s390x;linux-bionic-arm;linux-bionic-arm64;linux-bionic-x64;linux-bionic-x86;browser-wasm;wasi-wasm;ios-arm64;iossimulator-arm64;iossimulator-x64;tvos-arm64;tvossimulator-arm64;tvossimulator-x64;android-arm64;android-arm;android-x64;android-x86" RuntimePackLabels="Mono" Condition="'@(KnownRuntimePack)' == '' or !@(KnownRuntimePack->AnyHaveMetadataValue('TargetFramework', '$(NetCoreAppCurrent)'))"/> @@ -67,7 +67,7 @@ ExcludedRuntimeIdentifiers="android" AppHostPackNamePattern="$(LocalFrameworkOverrideName).Host.**RID**" AppHostPackVersion="$(ProductVersion)" - AppHostRuntimeIdentifiers="linux-arm;linux-arm64;linux-musl-arm64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;tizen.4.0.0-armel;tizen.5.0.0-armel;win-arm;win-arm64;win-x64;win-x86;linux-musl-arm;osx-arm64;linux-s390x;linux-bionic-arm;linux-bionic-arm64;linux-bionic-x64;linux-bionic-x86" + AppHostRuntimeIdentifiers="linux-arm;linux-arm64;linux-musl-arm64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;tizen.4.0.0-armel;tizen.5.0.0-armel;win-arm64;win-x64;win-x86;linux-musl-arm;osx-arm64;linux-s390x;linux-bionic-arm;linux-bionic-arm64;linux-bionic-x64;linux-bionic-x86" TargetFramework="$(NetCoreAppCurrent)" Condition="'@(KnownAppHostPack)' == '' or !@(KnownAppHostPack->AnyHaveMetadataValue('TargetFramework', '$(NetCoreAppCurrent)'))" /> diff --git a/eng/testing/ProvisioningVersions.props b/eng/testing/ProvisioningVersions.props index 4f2df8f136f7d4..7f555c06db3bca 100644 --- a/eng/testing/ProvisioningVersions.props +++ b/eng/testing/ProvisioningVersions.props @@ -44,7 +44,7 @@ - true + false diff --git a/eng/testing/performance/blazor_perf.proj b/eng/testing/performance/blazor_perf.proj index 4c6881dfbb05e4..a526a8cc3b5de3 100644 --- a/eng/testing/performance/blazor_perf.proj +++ b/eng/testing/performance/blazor_perf.proj @@ -3,11 +3,14 @@ %HELIX_WORKITEM_UPLOAD_ROOT%\ %24{HELIX_WORKITEM_UPLOAD_ROOT}/ + set RestoreAdditionalProjectSources=%HELIX_CORRELATION_PAYLOAD%\built-nugets & + export RestoreAdditionalProjectSources=$HELIX_CORRELATION_PAYLOAD/built-nugets && + python3 $(HelixPreCommands);chmod +x $HELIX_WORKITEM_PAYLOAD/SOD/SizeOnDisk --has-workload --readonly-dotnet --msbuild "/p:_TrimmerDumpDependencies=true" --msbuild /warnaserror:NU1602,NU1604 --msbuild-static AdditionalMonoLinkerOptions=%27"%24(AdditionalMonoLinkerOptions) --dump-dependencies"%27 --binlog $(LogDirectory)blazor_publish.binlog - $(Python) pre.py publish $(PublishArgs) + $(EnvVars) $(Python) pre.py publish $(PublishArgs) diff --git a/eng/testing/performance/ios_scenarios.proj b/eng/testing/performance/ios_scenarios.proj index 6b30417fdff479..3801fd935d96f8 100644 --- a/eng/testing/performance/ios_scenarios.proj +++ b/eng/testing/performance/ios_scenarios.proj @@ -17,6 +17,8 @@ nollvm llvm + symbols + nosymbols @@ -28,19 +30,19 @@ - + $(WorkItemDirectory) - cd $(ScenarioDirectory)helloios;cp -rf $HELIX_CORRELATION_PAYLOAD/iosHelloWorld/$(LlvmPath) ./app;$(Python) pre.py --name app + cd $(ScenarioDirectory)helloios;cp -rf $HELIX_CORRELATION_PAYLOAD/iosHelloWorld ./app;$(Python) pre.py --name app $(Python) test.py sod --scenario-name "%(Identity)" $(Python) post.py - + $(WorkItemDirectory) - cd $(ScenarioDirectory)helloios;cp -v $HELIX_CORRELATION_PAYLOAD/iosHelloWorldZip/$(LlvmPath)zip/iOSSampleApp$(LlvmPath)/iOSSampleApp$(LlvmPath).zip .;$(Python) pre.py --name iOSSampleApp$(LlvmPath).zip + cd $(ScenarioDirectory)helloios;cp -v $HELIX_CORRELATION_PAYLOAD/iosHelloWorldZip/iOSSampleApp.zip .;$(Python) pre.py --name iOSSampleApp.zip $(Python) test.py sod --scenario-name "%(Identity)" $(Python) post.py - + $(WorkItemDirectory).zip 00:15:00 ios-device @@ -49,7 +51,7 @@ # PreCommands export XHARNESSPATH=$XHARNESS_CLI_PATH - cp -r $HELIX_CORRELATION_PAYLOAD/iosHelloWorld/$(LlvmPath)/HelloiOS.app $(ScenarioDirectory)helloios/HelloiOS.app + cp -r $HELIX_CORRELATION_PAYLOAD/iosHelloWorld/iosHelloWorld/HelloiOS.app $(ScenarioDirectory)helloios/HelloiOS.app cp -f embedded.mobileprovision $(ScenarioDirectory)helloios/HelloiOS.app cd $(ScenarioDirectory)helloios sign HelloiOS.app diff --git a/eng/testing/performance/performance-setup.ps1 b/eng/testing/performance/performance-setup.ps1 index 29e3d6199cb788..a826f39f045e17 100644 --- a/eng/testing/performance/performance-setup.ps1 +++ b/eng/testing/performance/performance-setup.ps1 @@ -22,10 +22,10 @@ Param( [string] $LogicalMachine="", [switch] $AndroidMono, [switch] $iOSMono, - [switch] $NoPGO, - [switch] $DynamicPGO, - [switch] $FullPGO, + [switch] $iOSNativeAOT, + [switch] $NoDynamicPGO, [switch] $iOSLlvmBuild, + [switch] $iOSStripSymbols, [string] $MauiVersion, [switch] $UseLocalCommitTime ) @@ -83,21 +83,18 @@ if($MonoDotnet -ne "") } } -if($NoPGO) +if($NoDynamicPGO) { - $Configurations += " PGOType=nopgo" -} -elseif($DynamicPGO) -{ - $Configurations += " PGOType=dynamicpgo" -} -elseif($FullPGO) -{ - $Configurations += " PGOType=fullpgo" + $Configurations += " PGOType=nodynamicpgo" } if ($iOSMono) { $Configurations += " iOSLlvmBuild=$iOSLlvmBuild" + $Configurations += " iOSStripSymbols=$iOSStripSymbols" +} + +if ($iOSNativeAOT) { + $Configurations += " iOSStripSymbols=$iOSStripSymbols" } # FIX ME: This is a workaround until we get this from the actual pipeline @@ -109,17 +106,9 @@ if($Branch.Contains("refs/heads/release")) $CommonSetupArguments="--channel $CleanedBranchName --queue $Queue --build-number $BuildNumber --build-configs $Configurations --architecture $Architecture" $SetupArguments = "--repository https://github.com/$Repository --branch $Branch --get-perf-hash --commit-sha $CommitSha $CommonSetupArguments" -if($NoPGO) -{ - $SetupArguments = "$SetupArguments --no-pgo" -} -elseif($DynamicPGO) -{ - $SetupArguments = "$SetupArguments --dynamic-pgo" -} -elseif($FullPGO) +if($NoDynamicPGO) { - $SetupArguments = "$SetupArguments --full-pgo" + $SetupArguments = "$SetupArguments --no-dynamic-pgo" } if($UseLocalCommitTime) @@ -196,6 +185,7 @@ Write-PipelineSetVariable -Name 'RunFromPerfRepo' -Value "$RunFromPerformanceRep Write-PipelineSetVariable -Name 'Compare' -Value "$Compare" -IsMultiJobVariable $false Write-PipelineSetVariable -Name 'MonoDotnet' -Value "$UsingMono" -IsMultiJobVariable $false Write-PipelineSetVariable -Name 'iOSLlvmBuild' -Value "$iOSLlvmBuild" -IsMultiJobVariable $false +Write-PipelineSetVariable -Name 'iOSStripSymbols' -Value "$iOSStripSymbols" -IsMultiJobVariable $false # Helix Arguments Write-PipelineSetVariable -Name 'Creator' -Value "$Creator" -IsMultiJobVariable $false diff --git a/eng/testing/performance/performance-setup.sh b/eng/testing/performance/performance-setup.sh index 871a745c3375d5..38fbbc1a980de3 100755 --- a/eng/testing/performance/performance-setup.sh +++ b/eng/testing/performance/performance-setup.sh @@ -36,7 +36,10 @@ use_latest_dotnet=false logical_machine= javascript_engine="v8" iosmono=false +iosnativeaot=false +runtimetype="" iosllvmbuild="" +iosstripsymbols="" maui_version="" use_local_commit_time=false only_sanity=false @@ -139,16 +142,8 @@ while (($# > 0)); do wasmaot=true shift 1 ;; - --nopgo) - nopgo=true - shift 1 - ;; - --dynamicpgo) - dynamicpgo=true - shift 1 - ;; - --fullpgo) - fullpgo=true + --nodynamicpgo) + nodynamicpgo=true shift 1 ;; --compare) @@ -171,10 +166,18 @@ while (($# > 0)); do iosmono=true shift 1 ;; + --iosnativeaot) + iosnativeaot=true + shift 1 + ;; --iosllvmbuild) iosllvmbuild=$2 shift 2 ;; + --iosstripsymbols) + iosstripsymbols=$2 + shift 2 + ;; --mauiversion) maui_version=$2 shift 2 @@ -222,12 +225,12 @@ while (($# > 0)); do echo " --dotnetversions Passed as '--dotnet-versions ' to the setup script" echo " --alpine Set for runs on Alpine" echo " --iosmono Set for ios Mono/Maui runs" + echo " --iosnativeaot Set for ios Native AOT runs" echo " --iosllvmbuild Set LLVM for iOS Mono/Maui runs" + echo " --iosstripsymbols Set STRIP_DEBUG_SYMBOLS for iOS Mono/Maui runs" echo " --mauiversion Set the maui version for Mono/Maui runs" echo " --uselocalcommittime Pass local runtime commit time to the setup script" - echo " --nopgo Set for No PGO runs" - echo " --dynamicpgo Set for dynamic PGO runs" - echo " --fullpgo Set for Full PGO runs" + echo " --nodynamicpgo Set for No dynamic PGO runs" echo "" exit 1 ;; @@ -329,21 +332,23 @@ if [[ "$monoaot" == "true" ]]; then fi if [[ "$iosmono" == "true" ]]; then - configurations="$configurations iOSLlvmBuild=$iosllvmbuild" + runtimetype="Mono" + configurations="$configurations iOSLlvmBuild=$iosllvmbuild iOSStripSymbols=$iosstripsymbols RuntimeType=$runtimetype" extra_benchmark_dotnet_arguments="$extra_benchmark_dotnet_arguments" fi -if [[ "$nopgo" == "true" ]]; then - configurations="$configurations PGOType=nopgo" -fi -if [[ "$dynamicpgo" == "true" ]]; then - configurations="$configurations PGOType=dynamicpgo" +if [[ "$iosnativeaot" == "true" ]]; then + runtimetype="NativeAOT" + configurations="$configurations iOSStripSymbols=$iosstripsymbols RuntimeType=$runtimetype" + extra_benchmark_dotnet_arguments="$extra_benchmark_dotnet_arguments" fi -if [[ "$fullpgo" == "true" ]]; then - configurations="$configurations PGOType=fullpgo" - extra_benchmark_dotnet_arguments="$extra_benchmark_dotnet_arguments --category-exclusion-filter NoAOT" + +if [[ "$nodynamicpgo" == "true" ]]; then + configurations="$configurations PGOType=nodynamicpgo" fi + + cleaned_branch_name="main" if [[ $branch == *"refs/heads/release"* ]]; then cleaned_branch_name=${branch/refs\/heads\//} @@ -406,14 +411,8 @@ if [[ -n "$dotnet_versions" ]]; then setup_arguments="$setup_arguments --dotnet-versions $dotnet_versions" fi -if [[ "$nopgo" == "true" ]]; then - setup_arguments="$setup_arguments --no-pgo" -fi -if [[ "$dynamicpgo" == "true" ]]; then - setup_arguments="$setup_arguments --dynamic-pgo" -fi -if [[ "$fullpgo" == "true" ]]; then - setup_arguments="$setup_arguments --full-pgo" +if [[ "$nodynamicpgo" == "true" ]]; then + setup_arguments="$setup_arguments --no-dynamic-pgo" fi if [[ "$monoaot" == "true" ]]; then @@ -434,16 +433,11 @@ if [[ "$use_baseline_core_run" == true ]]; then mv $baseline_core_root_directory $new_baseline_core_root fi -if [[ "$iosmono" == "true" ]]; then - if [[ "$iosllvmbuild" == "True" ]]; then - # LLVM Mono .app - mkdir -p $payload_directory/iosHelloWorld && cp -rv $source_directory/iosHelloWorld/llvm $payload_directory/iosHelloWorld - mkdir -p $payload_directory/iosHelloWorldZip/llvmzip && cp -rv $source_directory/iosHelloWorldZip/llvmzip $payload_directory/iosHelloWorldZip - else - # NoLLVM Mono .app - mkdir -p $payload_directory/iosHelloWorld && cp -rv $source_directory/iosHelloWorld/nollvm $payload_directory/iosHelloWorld - mkdir -p $payload_directory/iosHelloWorldZip/nollvmzip && cp -rv $source_directory/iosHelloWorldZip/nollvmzip $payload_directory/iosHelloWorldZip - fi +if [[ "$iosmono" == "true" || "$iosnativeaot" == "true" ]]; then + mkdir -p $payload_directory/iosHelloWorld && cp -rv $source_directory/iosHelloWorld $payload_directory/iosHelloWorld + mkdir -p $payload_directory/iosHelloWorldZip && cp -rv $source_directory/iosHelloWorldZip $payload_directory/iosHelloWorldZip + + find "$payload_directory/iosHelloWorldZip/" -type f -name "*.zip" -execdir mv {} "$payload_directory/iosHelloWorldZip/iOSSampleApp.zip" \; fi ci=true @@ -477,6 +471,8 @@ Write-PipelineSetVariable -name "Compare" -value "$compare" -is_multi_job_variab Write-PipelineSetVariable -name "MonoDotnet" -value "$using_mono" -is_multi_job_variable false Write-PipelineSetVariable -name "WasmDotnet" -value "$using_wasm" -is_multi_job_variable false Write-PipelineSetVariable -Name 'iOSLlvmBuild' -Value "$iosllvmbuild" -is_multi_job_variable false +Write-PipelineSetVariable -Name 'iOSStripSymbols' -Value "$iosstripsymbols" -is_multi_job_variable false +Write-PipelineSetVariable -Name 'RuntimeType' -Value "$runtimetype" -is_multi_job_variable false Write-PipelineSetVariable -name "OnlySanityCheck" -value "$only_sanity" -is_multi_job_variable false # Put it back to what was set on top of this script diff --git a/eng/testing/scenarios/BuildWasmAppsJobsList.txt b/eng/testing/scenarios/BuildWasmAppsJobsList.txt index 38e288f81cfa14..914e6a2f956ee1 100644 --- a/eng/testing/scenarios/BuildWasmAppsJobsList.txt +++ b/eng/testing/scenarios/BuildWasmAppsJobsList.txt @@ -11,6 +11,7 @@ Wasm.Build.Tests.BuildPublishTests Wasm.Build.Tests.CleanTests Wasm.Build.Tests.ConfigSrcTests Wasm.Build.Tests.IcuShardingTests +Wasm.Build.Tests.HybridGlobalizationTests Wasm.Build.Tests.InvariantGlobalizationTests Wasm.Build.Tests.MainWithArgsTests Wasm.Build.Tests.NativeBuildTests diff --git a/eng/testing/tests.singlefile.targets b/eng/testing/tests.singlefile.targets index 4db0bf2f448955..4f4bcb481073ac 100644 --- a/eng/testing/tests.singlefile.targets +++ b/eng/testing/tests.singlefile.targets @@ -29,10 +29,10 @@ $(CoreCLRAotSdkDir) $(NetCoreAppCurrentTestHostSharedFrameworkPath) $(NetCoreAppCurrentTestHostSharedFrameworkPath) - $(NoWarn);IL1005;IL2105;IL3000;IL3001;IL3002;IL3003 + $(NoWarn);IL1005;IL2105;IL3000;IL3001;IL3002;IL3003;IL3050;IL3051;IL3052;IL3053 partial true - true + false diff --git a/global.json b/global.json index d24eda92f8b044..778d73c6fe7963 100644 --- a/global.json +++ b/global.json @@ -8,9 +8,9 @@ "dotnet": "8.0.100-preview.4.23260.5" }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.23268.1", - "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.23268.1", - "Microsoft.DotNet.SharedFramework.Sdk": "8.0.0-beta.23268.1", + "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.23302.3", + "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.23302.3", + "Microsoft.DotNet.SharedFramework.Sdk": "8.0.0-beta.23302.3", "Microsoft.Build.NoTargets": "3.7.0", "Microsoft.Build.Traversal": "3.4.0", "Microsoft.NET.Sdk.IL": "8.0.0-preview.5.23279.2" diff --git a/src/coreclr/.nuget/Directory.Build.props b/src/coreclr/.nuget/Directory.Build.props index 150e9ccfb0b82b..885f7f10739850 100644 --- a/src/coreclr/.nuget/Directory.Build.props +++ b/src/coreclr/.nuget/Directory.Build.props @@ -110,9 +110,6 @@ x86 - - arm - arm64 diff --git a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs index 0ee478fa675458..bc06bf44bac99d 100644 --- a/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs +++ b/src/coreclr/System.Private.CoreLib/src/Internal/Runtime/InteropServices/ComActivator.cs @@ -620,15 +620,15 @@ public void CreateInstance( ref Guid riid, out IntPtr ppvObject) { - Type interfaceType = BasicClassFactory.GetValidatedInterfaceType(_classType, ref riid, pUnkOuter); + Type interfaceType = GetValidatedInterfaceType(_classType, ref riid, pUnkOuter); object obj = Activator.CreateInstance(_classType)!; if (pUnkOuter != null) { - obj = BasicClassFactory.CreateAggregatedObject(pUnkOuter, obj); + obj = CreateAggregatedObject(pUnkOuter, obj); } - ppvObject = BasicClassFactory.GetObjectAsInterface(obj, interfaceType); + ppvObject = GetObjectAsInterface(obj, interfaceType); } public void LockServer([MarshalAs(UnmanagedType.Bool)] bool fLock) diff --git a/src/coreclr/System.Private.CoreLib/src/System/Attribute.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Attribute.CoreCLR.cs index 258d0470e71b0e..9365f8ba0b8695 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Attribute.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Attribute.CoreCLR.cs @@ -515,10 +515,11 @@ public static bool IsDefined(MemberInfo element, Type attributeType, bool inheri if (attrib == null || attrib.Length == 0) return null; + Attribute match = attrib[0]; if (attrib.Length == 1) - return attrib[0]; + return match; - throw new AmbiguousMatchException(SR.RFLCT_AmbigCust); + throw ThrowHelper.GetAmbiguousMatchException(match); } #endregion @@ -614,10 +615,11 @@ public static bool IsDefined(ParameterInfo element, Type attributeType, bool inh if (attrib == null || attrib.Length == 0) return null; + Attribute match = attrib[0]; if (attrib.Length == 1) - return attrib[0]; + return match; - throw new AmbiguousMatchException(SR.RFLCT_AmbigCust); + throw ThrowHelper.GetAmbiguousMatchException(match); } #endregion @@ -683,10 +685,11 @@ public static bool IsDefined(Module element, Type attributeType, bool inherit) if (attrib == null || attrib.Length == 0) return null; + Attribute match = attrib[0]; if (attrib.Length == 1) - return attrib[0]; + return match; - throw new AmbiguousMatchException(SR.RFLCT_AmbigCust); + throw ThrowHelper.GetAmbiguousMatchException(match); } #endregion @@ -752,10 +755,11 @@ public static bool IsDefined(Assembly element, Type attributeType, bool inherit) if (attrib == null || attrib.Length == 0) return null; + Attribute match = attrib[0]; if (attrib.Length == 1) - return attrib[0]; + return match; - throw new AmbiguousMatchException(SR.RFLCT_AmbigCust); + throw ThrowHelper.GetAmbiguousMatchException(match); } #endregion diff --git a/src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/Comparer.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/Comparer.CoreCLR.cs index f6d531485b2925..5c2e18b3382b65 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/Comparer.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/Comparer.CoreCLR.cs @@ -16,7 +16,7 @@ internal sealed partial class EnumComparer : Comparer where T : struct, En { public override int Compare(T x, T y) { - return System.Runtime.CompilerServices.RuntimeHelpers.EnumCompareTo(x, y); + return RuntimeHelpers.EnumCompareTo(x, y); } } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/ComparerHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/ComparerHelpers.cs index b020c127629413..f07e70deaf8d88 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/ComparerHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/ComparerHelpers.cs @@ -41,7 +41,7 @@ internal static object CreateDefaultComparer(Type type) { // Nullable does not implement IComparable directly because that would add an extra interface call per comparison. var embeddedType = (RuntimeType)type.GetGenericArguments()[0]; - result = RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableComparer), embeddedType); + result = CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(NullableComparer), embeddedType); } // The comparer for enums is specialized to avoid boxing. else if (type.IsEnum) @@ -78,7 +78,7 @@ internal static object CreateDefaultComparer(Type type) case TypeCode.UInt32: case TypeCode.Int64: case TypeCode.UInt64: - return RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(EnumComparer<>), enumType); + return CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(EnumComparer<>), enumType); } return null; @@ -153,7 +153,7 @@ internal static object CreateDefaultEqualityComparer(Type type) case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.UInt16: - return RuntimeTypeHandle.CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(EnumEqualityComparer<>), enumType); + return CreateInstanceForAnotherGenericParameter((RuntimeType)typeof(EnumEqualityComparer<>), enumType); } return null; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.CoreCLR.cs index 2377566a05312a..bd4532bad23851 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Collections/Generic/EqualityComparer.CoreCLR.cs @@ -164,7 +164,7 @@ public sealed partial class EnumEqualityComparer : EqualityComparer where [MethodImpl(MethodImplOptions.AggressiveInlining)] public override bool Equals(T x, T y) { - return System.Runtime.CompilerServices.RuntimeHelpers.EnumEquals(x, y); + return RuntimeHelpers.EnumEquals(x, y); } internal override int IndexOf(T[] array, T value, int startIndex, int count) @@ -172,7 +172,7 @@ internal override int IndexOf(T[] array, T value, int startIndex, int count) int endIndex = startIndex + count; for (int i = startIndex; i < endIndex; i++) { - if (System.Runtime.CompilerServices.RuntimeHelpers.EnumEquals(array[i], value)) return i; + if (RuntimeHelpers.EnumEquals(array[i], value)) return i; } return -1; } @@ -182,7 +182,7 @@ internal override int LastIndexOf(T[] array, T value, int startIndex, int count) int endIndex = startIndex - count + 1; for (int i = startIndex; i >= endIndex; i--) { - if (System.Runtime.CompilerServices.RuntimeHelpers.EnumEquals(array[i], value)) return i; + if (RuntimeHelpers.EnumEquals(array[i], value)) return i; } return -1; } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs index e184ddfe89ed37..7fd8ed40d57b82 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Delegate.CoreCLR.cs @@ -131,7 +131,7 @@ public override bool Equals([NotNullWhen(true)] object? obj) // method ptrs don't match, go down long path // if (_methodBase == null || d._methodBase == null || !(_methodBase is MethodInfo) || !(d._methodBase is MethodInfo)) - return Delegate.InternalEqualMethodHandles(this, d); + return InternalEqualMethodHandles(this, d); else return _methodBase.Equals(d._methodBase); } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.PortableThreadPool.NativeSinks.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.PortableThreadPool.NativeSinks.CoreCLR.cs index cbf6e4665e78ce..c618f1d5203e4e 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.PortableThreadPool.NativeSinks.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Diagnostics/Eventing/NativeRuntimeEventSource.PortableThreadPool.NativeSinks.CoreCLR.cs @@ -34,7 +34,7 @@ internal sealed partial class NativeRuntimeEventSource : EventSource [NonEvent] [LibraryImport(RuntimeHelpers.QCall)] - internal static partial void LogThreadPoolWorkerThreadAdjustmentAdjustment(double AverageThroughput, uint NewWorkerThreadCount, NativeRuntimeEventSource.ThreadAdjustmentReasonMap Reason, ushort ClrInstanceID); + internal static partial void LogThreadPoolWorkerThreadAdjustmentAdjustment(double AverageThroughput, uint NewWorkerThreadCount, ThreadAdjustmentReasonMap Reason, ushort ClrInstanceID); [NonEvent] [LibraryImport(RuntimeHelpers.QCall)] diff --git a/src/coreclr/System.Private.CoreLib/src/System/GC.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/GC.CoreCLR.cs index 20c7159380959e..d59ad132ef59ee 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/GC.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/GC.CoreCLR.cs @@ -17,13 +17,14 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; +using System.Runtime.Versioning; namespace System { /// Specifies the behavior for a forced garbage collection. public enum GCCollectionMode { - /// The default setting for this enumeration, which is currently . + /// The default setting for this enumeration, which is currently . Default = 0, /// Forces the garbage collection to occur immediately. @@ -352,8 +353,8 @@ public static long GetTotalMemory(bool forceFullCollection) float diff; do { - GC.WaitForPendingFinalizers(); - GC.Collect(); + WaitForPendingFinalizers(); + Collect(); size = newSize; newSize = GetTotalMemory(); diff = ((float)(newSize - size)) / size; @@ -640,8 +641,8 @@ internal enum EnableNoGCRegionCallbackStatus /// Register a callback to be invoked when we allocated a certain amount of memory in the no GC region. /// The total size of the no GC region. Must be a number > 0 or an ArgumentOutOfRangeException will be thrown. /// The callback to be executed when we allocated a certain amount of memory in the no GC region.. - /// The argument is less than or equal to 0. - /// The argument is null. + /// The argument is less than or equal to 0. + /// The argument is null. /// The GC is not currently under a NoGC region. /// -or- /// Another callback is already registered. @@ -907,7 +908,7 @@ internal enum RefreshMemoryStatus /// If the hard limit is invalid. This can happen, for example, with negative heap hard limit percentages." /// /// - [System.Runtime.Versioning.RequiresPreviewFeaturesAttribute("RefreshMemoryLimit is in preview.")] + [RequiresPreviewFeatures("RefreshMemoryLimit is in preview.")] public static void RefreshMemoryLimit() { ulong heapHardLimit = (AppContext.GetData("GCHeapHardLimit") as ulong?) ?? ulong.MaxValue; diff --git a/src/coreclr/System.Private.CoreLib/src/System/IO/FileLoadException.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/IO/FileLoadException.CoreCLR.cs index 4933f9189f133b..439689ca9adc26 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/IO/FileLoadException.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/IO/FileLoadException.CoreCLR.cs @@ -23,7 +23,7 @@ internal static string FormatFileLoadExceptionMessage(string? fileName, int hRes GetFileLoadExceptionMessage(hResult, new StringHandleOnStack(ref format)); string? message = null; - if (hResult == System.HResults.COR_E_BADEXEFORMAT) + if (hResult == HResults.COR_E_BADEXEFORMAT) message = SR.Arg_BadImageFormatException; else GetMessageForHR(hResult, new StringHandleOnStack(ref message)); diff --git a/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs b/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs index 5410a6c2460732..038d8db6084119 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/MulticastDelegate.cs @@ -5,6 +5,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reflection; +using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; @@ -43,7 +44,7 @@ internal bool IsUnmanagedFunctionPtr() internal bool InvocationListLogicallyNull() { - return (_invocationList == null) || (_invocationList is LoaderAllocator) || (_invocationList is System.Reflection.Emit.DynamicResolver); + return (_invocationList == null) || (_invocationList is LoaderAllocator) || (_invocationList is DynamicResolver); } [Obsolete(Obsoletions.LegacyFormatterImplMessage, DiagnosticId = Obsoletions.LegacyFormatterImplDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] @@ -59,7 +60,7 @@ public sealed override bool Equals([NotNullWhen(true)] object? obj) { if (obj == null) return false; - if (object.ReferenceEquals(this, obj)) + if (ReferenceEquals(this, obj)) return true; if (!InternalEqualTypes(this, obj)) return false; @@ -158,7 +159,7 @@ private bool InvocationListEquals(MulticastDelegate d) private static bool TrySetSlot(object?[] a, int index, object o) { - if (a[index] == null && System.Threading.Interlocked.CompareExchange(ref a[index], o, null) == null) + if (a[index] == null && Threading.Interlocked.CompareExchange(ref a[index], o, null) == null) return true; // The slot may be already set because we have added and removed the same method before. @@ -565,13 +566,13 @@ protected override MethodInfo GetMethodImpl() // this should help inlining [DoesNotReturn] - [System.Diagnostics.DebuggerNonUserCode] + [DebuggerNonUserCode] private static void ThrowNullThisInDelegateToInstance() => throw new ArgumentException(SR.Arg_DlgtNullInst); #pragma warning disable IDE0060 - [System.Diagnostics.DebuggerNonUserCode] - [System.Diagnostics.DebuggerStepThrough] + [DebuggerNonUserCode] + [DebuggerStepThrough] private void CtorClosed(object target, IntPtr methodPtr) { if (target == null) @@ -580,24 +581,24 @@ private void CtorClosed(object target, IntPtr methodPtr) this._methodPtr = methodPtr; } - [System.Diagnostics.DebuggerNonUserCode] - [System.Diagnostics.DebuggerStepThrough] + [DebuggerNonUserCode] + [DebuggerStepThrough] private void CtorClosedStatic(object target, IntPtr methodPtr) { this._target = target; this._methodPtr = methodPtr; } - [System.Diagnostics.DebuggerNonUserCode] - [System.Diagnostics.DebuggerStepThrough] + [DebuggerNonUserCode] + [DebuggerStepThrough] private void CtorRTClosed(object target, IntPtr methodPtr) { this._target = target; this._methodPtr = AdjustTarget(target, methodPtr); } - [System.Diagnostics.DebuggerNonUserCode] - [System.Diagnostics.DebuggerStepThrough] + [DebuggerNonUserCode] + [DebuggerStepThrough] private void CtorOpened(object target, IntPtr methodPtr, IntPtr shuffleThunk) { this._target = this; @@ -605,8 +606,8 @@ private void CtorOpened(object target, IntPtr methodPtr, IntPtr shuffleThunk) this._methodPtrAux = methodPtr; } - [System.Diagnostics.DebuggerNonUserCode] - [System.Diagnostics.DebuggerStepThrough] + [DebuggerNonUserCode] + [DebuggerStepThrough] private void CtorVirtualDispatch(object target, IntPtr methodPtr, IntPtr shuffleThunk) { this._target = this; @@ -614,33 +615,33 @@ private void CtorVirtualDispatch(object target, IntPtr methodPtr, IntPtr shuffle this._methodPtrAux = GetCallStub(methodPtr); } - [System.Diagnostics.DebuggerNonUserCode] - [System.Diagnostics.DebuggerStepThrough] + [DebuggerNonUserCode] + [DebuggerStepThrough] private void CtorCollectibleClosedStatic(object target, IntPtr methodPtr, IntPtr gchandle) { this._target = target; this._methodPtr = methodPtr; - this._methodBase = System.Runtime.InteropServices.GCHandle.InternalGet(gchandle); + this._methodBase = GCHandle.InternalGet(gchandle); } - [System.Diagnostics.DebuggerNonUserCode] - [System.Diagnostics.DebuggerStepThrough] + [DebuggerNonUserCode] + [DebuggerStepThrough] private void CtorCollectibleOpened(object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr gchandle) { this._target = this; this._methodPtr = shuffleThunk; this._methodPtrAux = methodPtr; - this._methodBase = System.Runtime.InteropServices.GCHandle.InternalGet(gchandle); + this._methodBase = GCHandle.InternalGet(gchandle); } - [System.Diagnostics.DebuggerNonUserCode] - [System.Diagnostics.DebuggerStepThrough] + [DebuggerNonUserCode] + [DebuggerStepThrough] private void CtorCollectibleVirtualDispatch(object target, IntPtr methodPtr, IntPtr shuffleThunk, IntPtr gchandle) { this._target = this; this._methodPtr = shuffleThunk; this._methodPtrAux = GetCallStub(methodPtr); - this._methodBase = System.Runtime.InteropServices.GCHandle.InternalGet(gchandle); + this._methodBase = GCHandle.InternalGet(gchandle); } #pragma warning restore IDE0060 } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Assembly.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Assembly.CoreCLR.cs index a2aa467d9a8c38..a0d06e8e8197bc 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Assembly.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Assembly.CoreCLR.cs @@ -6,6 +6,7 @@ using System.Runtime.InteropServices; using System.Runtime.Loader; using System.Runtime.Serialization; +using System.Security; using StackCrawlMark = System.Threading.StackCrawlMark; namespace System.Reflection @@ -14,7 +15,7 @@ public abstract partial class Assembly : ICustomAttributeProvider, ISerializable { // Locate an assembly by the long form of the assembly name. // eg. "Toolbox.dll, version=1.1.10.1220, locale=en, publickey=1234567890123456789012345678901234567890" - [System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod + [DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod public static Assembly Load(string assemblyString) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -22,7 +23,7 @@ public static Assembly Load(string assemblyString) } [Obsolete("Assembly.LoadWithPartialName has been deprecated. Use Assembly.Load() instead.")] - [System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod + [DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod public static Assembly? LoadWithPartialName(string partialName) { ArgumentNullException.ThrowIfNull(partialName); @@ -43,7 +44,7 @@ public static Assembly Load(string assemblyString) // Locate an assembly by its name. The name can be strong or // weak. The assembly is loaded into the domain of the caller. - [System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod + [DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod public static Assembly Load(AssemblyName assemblyRef) { ArgumentNullException.ThrowIfNull(assemblyRef); @@ -63,14 +64,14 @@ internal static RuntimeAssembly GetExecutingAssembly(ref StackCrawlMark stackMar } // Get the assembly that the current code is running from. - [System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod + [DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod public static Assembly GetExecutingAssembly() { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; return GetExecutingAssembly(ref stackMark); } - [System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod + [DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod public static Assembly GetCallingAssembly() { // LookForMyCallersCaller is not guaranteed to return the correct stack frame diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeAssemblyBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeAssemblyBuilder.cs index dd6c84158a01fe..d008fed2a107b5 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeAssemblyBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeAssemblyBuilder.cs @@ -22,7 +22,7 @@ public partial class AssemblyBuilder [RequiresDynamicCode("Defining a dynamic assembly requires dynamic code.")] [DynamicSecurityMethod] // Required to make Assembly.GetCallingAssembly reliable. public static AssemblyBuilder DefineDynamicAssembly(AssemblyName name, AssemblyBuilderAccess access) - => DefineDynamicAssembly(name, access, null, Assembly.GetCallingAssembly()); + => DefineDynamicAssembly(name, access, null, GetCallingAssembly()); [RequiresDynamicCode("Defining a dynamic assembly requires dynamic code.")] [DynamicSecurityMethod] // Required to make Assembly.GetCallingAssembly reliable. @@ -30,7 +30,7 @@ public static AssemblyBuilder DefineDynamicAssembly( AssemblyName name, AssemblyBuilderAccess access, IEnumerable? assemblyAttributes) - => DefineDynamicAssembly(name, access, assemblyAttributes, Assembly.GetCallingAssembly()); + => DefineDynamicAssembly(name, access, assemblyAttributes, GetCallingAssembly()); private static RuntimeAssemblyBuilder DefineDynamicAssembly( AssemblyName name, diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeEnumBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeEnumBuilder.cs index 2e14270c0d0265..1d0703dc51c02e 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeEnumBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeEnumBuilder.cs @@ -334,7 +334,7 @@ internal RuntimeEnumBuilder( // Client should not set any bits other than the visibility bits. if ((visibility & ~TypeAttributes.VisibilityMask) != 0) throw new ArgumentException(SR.Argument_ShouldOnlySetVisibilityFlags, nameof(name)); - m_typeBuilder = new RuntimeTypeBuilder(name, visibility | TypeAttributes.Sealed, typeof(System.Enum), null, module, PackingSize.Unspecified, TypeBuilder.UnspecifiedTypeSize, null); + m_typeBuilder = new RuntimeTypeBuilder(name, visibility | TypeAttributes.Sealed, typeof(Enum), null, module, PackingSize.Unspecified, TypeBuilder.UnspecifiedTypeSize, null); // Define the underlying field for the enum. It will be a non-static, private field with special name bit set. m_underlyingField = m_typeBuilder.DefineField("value__", underlyingType, FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.cs index f0cf9e6440341c..3c2daf38b082f2 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeMethodBuilder.cs @@ -718,7 +718,7 @@ private static bool IsKnownCA(ConstructorInfo con) private void ParseCA(ConstructorInfo con) { Type? caType = con.DeclaringType; - if (caType == typeof(System.Runtime.CompilerServices.MethodImplAttribute)) + if (caType == typeof(MethodImplAttribute)) { // dig through the blob looking for the MethodImplAttributes flag // that must be in the MethodCodeType field diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.cs index 79aaaebd328b13..c9147ca420a28e 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.cs @@ -574,7 +574,7 @@ private FieldBuilder DefineDataHelper(string name, byte[]? data, int size, Field typeAttributes = TypeAttributes.Public | TypeAttributes.ExplicitLayout | TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.AnsiClass; // Define the backing value class - valueClassType = m_module.DefineType(strValueClassName, typeAttributes, typeof(System.ValueType), PackingSize.Size1, size); + valueClassType = m_module.DefineType(strValueClassName, typeAttributes, typeof(ValueType), PackingSize.Size1, size); valueClassType.CreateType(); } @@ -827,7 +827,7 @@ public override Type[] GetInterfaces() if (m_typeInterfaces == null) { - return Type.EmptyTypes; + return EmptyTypes; } return m_typeInterfaces.ToArray(); @@ -1134,7 +1134,7 @@ protected override GenericTypeParameterBuilder[] DefineGenericParametersCore(par return m_inst; } - public override Type[] GetGenericArguments() => m_inst ?? Type.EmptyTypes; + public override Type[] GetGenericArguments() => m_inst ?? EmptyTypes; // If a TypeBuilder is generic, it must be a generic type definition // All instantiated generic types are TypeBuilderInstantiation. diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdFieldInfo.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdFieldInfo.cs index 7d5cd5328e81f1..cda066bba16e20 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdFieldInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MdFieldInfo.cs @@ -64,22 +64,22 @@ public override int GetHashCode() => public override bool IsSecuritySafeCritical => DeclaringType!.IsSecuritySafeCritical; public override bool IsSecurityTransparent => DeclaringType!.IsSecurityTransparent; - [DebuggerStepThroughAttribute] - [Diagnostics.DebuggerHidden] + [DebuggerStepThrough] + [DebuggerHidden] public override object? GetValueDirect(TypedReference obj) { return GetValue(null); } - [DebuggerStepThroughAttribute] - [Diagnostics.DebuggerHidden] + [DebuggerStepThrough] + [DebuggerHidden] public override void SetValueDirect(TypedReference obj, object value) { throw new FieldAccessException(SR.Acc_ReadOnly); } - [DebuggerStepThroughAttribute] - [Diagnostics.DebuggerHidden] + [DebuggerStepThrough] + [DebuggerHidden] public override object? GetValue(object? obj) { return GetValue(false); @@ -99,8 +99,8 @@ public override void SetValueDirect(TypedReference obj, object value) return value; } - [DebuggerStepThroughAttribute] - [Diagnostics.DebuggerHidden] + [DebuggerStepThrough] + [DebuggerHidden] public override void SetValue(object? obj, object? value, BindingFlags invokeAttr, Binder? binder, CultureInfo? culture) { throw new FieldAccessException(SR.Acc_ReadOnly); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Metadata/AssemblyExtensions.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Metadata/AssemblyExtensions.cs index bae43fd0e9147d..c3dbc2a73f2d6c 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Metadata/AssemblyExtensions.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Metadata/AssemblyExtensions.cs @@ -20,7 +20,7 @@ public static partial class AssemblyExtensions /// When this method returns, contains the length of the metadata section blob. /// /// if the metadata is retrieved successfully; upon failure. - /// The metadata might not be available for some assemblies, such as , AOT images, etc. + /// The metadata might not be available for some assemblies, such as , AOT images, etc. /// /// /// Callers should not write to the metadata blob. diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs index afed33fe1f3bc2..e8bb0fa1814939 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/MethodBase.CoreCLR.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; +using System.Security; using System.Threading; namespace System.Reflection @@ -34,7 +35,7 @@ public abstract partial class MethodBase : MemberInfo } [RequiresUnreferencedCode("Metadata for the method might be incomplete or removed")] - [System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod + [DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod public static MethodBase? GetCurrentMethod() { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/ModifiedType.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/ModifiedType.CoreCLR.cs index 60ab5dd00d102d..394b6b4ecffa9e 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/ModifiedType.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/ModifiedType.CoreCLR.cs @@ -30,6 +30,6 @@ internal static Type Create(Type unmodifiedType, Signature? signature, int param private Type[] GetCustomModifiers(bool required) => (_typeSignature._signature != null) ? - _typeSignature._signature.GetCustomModifiersAtOffset(_typeSignature._offset, required) : Type.EmptyTypes; + _typeSignature._signature.GetCustomModifiersAtOffset(_typeSignature._offset, required) : EmptyTypes; } } 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 10fd2c215dd6ac..26e75846401dfc 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeAssembly.cs @@ -14,6 +14,7 @@ using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Threading; +using System.Security; namespace System.Reflection { @@ -344,7 +345,7 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont public override Module ManifestModule => // We don't need to return the "external" ModuleBuilder because // it is meant to be read-only - RuntimeAssembly.GetManifestModule(GetNativeHandle()); + GetManifestModule(GetNativeHandle()); public override object[] GetCustomAttributes(bool inherit) { @@ -657,7 +658,7 @@ public override Assembly GetSatelliteAssembly(CultureInfo culture, Version? vers return InternalGetSatelliteAssembly(culture, version, throwOnFileNotFound: true)!; } - [System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod + [DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod internal Assembly? InternalGetSatelliteAssembly(CultureInfo culture, Version? version, bool throwOnFileNotFound) 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 c601a2d7d08997..f3578517a4df78 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeCustomAttributeData.cs @@ -928,7 +928,7 @@ internal static object[] GetCustomAttributes(RuntimeType type, RuntimeType caTyp // if we are asked to go up the hierarchy chain we have to do it now and regardless of the // attribute usage for the specific attribute because a derived attribute may override the usage... // ... however if the attribute is sealed we can rely on the attribute usage - if (!inherit || (caType.IsSealed && !CustomAttribute.GetAttributeUsage(caType).Inherited)) + if (!inherit || (caType.IsSealed && !GetAttributeUsage(caType).Inherited)) { object[] attributes = GetCustomAttributes(type.GetRuntimeModule(), type.MetadataToken, pcas.Count, caType); if (pcas.Count > 0) pcas.CopyTo(attributes, attributes.Length - pcas.Count); @@ -970,7 +970,7 @@ internal static object[] GetCustomAttributes(RuntimeMethodInfo method, RuntimeTy // if we are asked to go up the hierarchy chain we have to do it now and regardless of the // attribute usage for the specific attribute because a derived attribute may override the usage... // ... however if the attribute is sealed we can rely on the attribute usage - if (!inherit || (caType.IsSealed && !CustomAttribute.GetAttributeUsage(caType).Inherited)) + if (!inherit || (caType.IsSealed && !GetAttributeUsage(caType).Inherited)) { object[] attributes = GetCustomAttributes(method.GetRuntimeModule(), method.MetadataToken, pcas.Count, caType); if (pcas.Count > 0) pcas.CopyTo(attributes, attributes.Length - pcas.Count); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs index 0d25286564e343..24634ed9715fe2 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeMethodInfo.CoreCLR.cs @@ -454,7 +454,7 @@ public override MethodInfo MakeGenericMethod(params Type[] methodInstantiation) for (int iCopy = 0; iCopy < methodInstantiation.Length; iCopy++) methodInstantiationCopy[iCopy] = methodInstantiation[iCopy]; methodInstantiation = methodInstantiationCopy; - return System.Reflection.Emit.MethodBuilderInstantiation.MakeGenericMethod(this, methodInstantiation); + return Emit.MethodBuilderInstantiation.MakeGenericMethod(this, methodInstantiation); } methodInstantionRuntimeType[i] = rtMethodInstantiationElem; 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 0f8683c6633e47..a3a98b78af9a5a 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeModule.cs @@ -512,7 +512,7 @@ public override string Name { string s = GetFullyQualifiedName(); - int i = s.LastIndexOf(System.IO.Path.DirectorySeparatorChar); + int i = s.LastIndexOf(IO.Path.DirectorySeparatorChar); if (i < 0) return s; 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 6ae15363e51175..5af77b790f49c3 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs @@ -259,9 +259,7 @@ public override bool HasDefaultValue if (m_noMetadata || m_noDefaultValue) return false; - object? defaultValue = GetDefaultValueInternal(false); - - return defaultValue != DBNull.Value; + return TryGetDefaultValueInternal(false, out _); } } @@ -277,9 +275,7 @@ public override bool HasDefaultValue return null; // for dynamic method we pretend to have cached the value so we do not go to metadata - object? defaultValue = GetDefaultValueInternal(raw); - - if (defaultValue == DBNull.Value) + if (!TryGetDefaultValueInternal(raw, out object? defaultValue)) { #region Handle case if no default value was found if (IsOptional) @@ -295,7 +291,7 @@ public override bool HasDefaultValue private object? GetDefaultValueFromCustomAttributeData() { - foreach (CustomAttributeData attributeData in RuntimeCustomAttributeData.GetCustomAttributes(this)) + foreach (CustomAttributeData attributeData in CustomAttributeData.GetCustomAttributes(this)) { Type attributeType = attributeData.AttributeType; if (attributeType == typeof(DecimalConstantAttribute)) @@ -328,23 +324,21 @@ public override bool HasDefaultValue } // returns DBNull.Value if the parameter doesn't have a default value - private object? GetDefaultValueInternal(bool raw) + private bool TryGetDefaultValueInternal(bool raw, out object? defaultValue) { Debug.Assert(!m_noMetadata); - if (m_noDefaultValue) - return DBNull.Value; - - object? defaultValue = null; + if (m_noDefaultValue || MdToken.IsNullToken(m_tkParamDef)) + { + defaultValue = DBNull.Value; + m_noDefaultValue = true; + return false; + } // Prioritize metadata constant over custom attribute constant #region Look for a default value in metadata - if (!MdToken.IsNullToken(m_tkParamDef)) - { - // 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); - } - #endregion + // 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); // If default value is not specified in metadata, look for it in custom attributes if (defaultValue == DBNull.Value) @@ -357,18 +351,23 @@ public override bool HasDefaultValue // IMPORTANT: Please note that there is a subtle difference in order custom attributes are inspected for // RawDefaultValue and DefaultValue. defaultValue = raw ? GetDefaultValueFromCustomAttributeData() : GetDefaultValueFromCustomAttributes(); + + if (defaultValue == DBNull.Value) + { + m_noDefaultValue = true; + return false; + } } - if (defaultValue == DBNull.Value) - m_noDefaultValue = true; + return true; - return defaultValue; + #endregion } private static decimal GetRawDecimalConstant(CustomAttributeData attr) { Debug.Assert(attr.Constructor.DeclaringType == typeof(DecimalConstantAttribute)); - System.Collections.Generic.IList args = attr.ConstructorArguments; + IList args = attr.ConstructorArguments; Debug.Assert(args.Count == 5); return new decimal( 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 c48c24dd7e7a34..d2731883b02f89 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/RuntimePropertyInfo.cs @@ -331,26 +331,26 @@ internal ParameterInfo[] GetIndexParametersNoCopy() #endregion #region Dynamic - [DebuggerStepThroughAttribute] - [Diagnostics.DebuggerHidden] + [DebuggerStepThrough] + [DebuggerHidden] public override object? GetValue(object? obj, object?[]? index) { return GetValue(obj, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static, null, index, null); } - [DebuggerStepThroughAttribute] - [Diagnostics.DebuggerHidden] + [DebuggerStepThrough] + [DebuggerHidden] public override object? GetValue(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? index, CultureInfo? culture) { RuntimeMethodInfo? m = GetGetMethod(true); if (m == null) - throw new ArgumentException(System.SR.Arg_GetMethNotFnd); + throw new ArgumentException(SR.Arg_GetMethNotFnd); return m.Invoke(obj, invokeAttr, binder, index, null); } - [DebuggerStepThroughAttribute] - [Diagnostics.DebuggerHidden] + [DebuggerStepThrough] + [DebuggerHidden] public override void SetValue(object? obj, object? value, object?[]? index) { SetValue(obj, @@ -361,14 +361,14 @@ public override void SetValue(object? obj, object? value, object?[]? index) null); } - [DebuggerStepThroughAttribute] - [Diagnostics.DebuggerHidden] + [DebuggerStepThrough] + [DebuggerHidden] public override void SetValue(object? obj, object? value, BindingFlags invokeAttr, Binder? binder, object?[]? index, CultureInfo? culture) { RuntimeMethodInfo? m = GetSetMethod(true); if (m == null) - throw new ArgumentException(System.SR.Arg_SetMethNotFnd); + throw new ArgumentException(SR.Arg_SetMethNotFnd); if (index is 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 7a44b24f5b6741..831582694aa534 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 @@ -49,7 +49,7 @@ public static partial class RuntimeHelpers // This call will generate an exception if the specified class constructor threw an // exception when it ran. - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ReflectionInvocation_RunClassConstructor")] + [LibraryImport(QCall, EntryPoint = "ReflectionInvocation_RunClassConstructor")] private static partial void RunClassConstructor(QCallTypeHandle type); [RequiresUnreferencedCode("Trimmer can't guarantee existence of class constructor")] @@ -70,7 +70,7 @@ public static void RunClassConstructor(RuntimeTypeHandle type) // This call will generate an exception if the specified module constructor threw an // exception when it ran. - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ReflectionInvocation_RunModuleConstructor")] + [LibraryImport(QCall, EntryPoint = "ReflectionInvocation_RunModuleConstructor")] private static partial void RunModuleConstructor(QCallModule module); public static void RunModuleConstructor(ModuleHandle module) @@ -82,10 +82,10 @@ public static void RunModuleConstructor(ModuleHandle module) RunModuleConstructor(new QCallModule(ref rm)); } - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ReflectionInvocation_CompileMethod")] + [LibraryImport(QCall, EntryPoint = "ReflectionInvocation_CompileMethod")] internal static partial void CompileMethod(RuntimeMethodHandleInternal method); - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ReflectionInvocation_PrepareMethod")] + [LibraryImport(QCall, EntryPoint = "ReflectionInvocation_PrepareMethod")] private static unsafe partial void PrepareMethod(RuntimeMethodHandleInternal method, IntPtr* pInstantiation, int cInstantiation); public static void PrepareMethod(RuntimeMethodHandle method) => PrepareMethod(method, null); @@ -133,7 +133,7 @@ public static int OffsetToStringData { // This offset is baked in by string indexer intrinsic, so there is no harm // in getting it baked in here as well. - [System.Runtime.Versioning.NonVersionable] + [NonVersionable] get => // Number of bytes from the address pointed to by a reference to // a String to the first 16-bit character in the String. Skip @@ -182,7 +182,7 @@ public static object GetUninitializedObject( return obj!; } - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "ReflectionSerialization_GetUninitializedObject")] + [LibraryImport(QCall, EntryPoint = "ReflectionSerialization_GetUninitializedObject")] private static partial void GetUninitializedObject(QCallTypeHandle type, ObjectHandleOnStack retObject); [MethodImpl(MethodImplOptions.InternalCall)] @@ -309,13 +309,13 @@ internal static unsafe bool ObjectHasComponentSize(object obj) } - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "MethodTable_AreTypesEquivalent")] + [LibraryImport(QCall, EntryPoint = "MethodTable_AreTypesEquivalent")] [return: MarshalAs(UnmanagedType.Bool)] internal static unsafe partial bool AreTypesEquivalent(MethodTable* pMTa, MethodTable* pMTb); /// /// Allocate memory that is associated with the and - /// will be freed if and when the is unloaded. + /// will be freed if and when the is unloaded. /// /// Type associated with the allocated memory. /// Amount of memory in bytes to allocate. @@ -330,7 +330,7 @@ public static IntPtr AllocateTypeAssociatedMemory(Type type, int size) return AllocateTypeAssociatedMemory(new QCallTypeHandle(ref rt), (uint)size); } - [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "RuntimeTypeHandle_AllocateTypeAssociatedMemory")] + [LibraryImport(QCall, EntryPoint = "RuntimeTypeHandle_AllocateTypeAssociatedMemory")] private static partial IntPtr AllocateTypeAssociatedMemory(QCallTypeHandle type, uint size); [MethodImpl(MethodImplOptions.InternalCall)] diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/ControlledExecution.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/ControlledExecution.CoreCLR.cs index b6c437b351b7b1..67971b90caa1b6 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/ControlledExecution.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/ControlledExecution.CoreCLR.cs @@ -21,12 +21,12 @@ public static partial class ControlledExecution /// /// The delegate that represents the code to execute. /// The cancellation token that may be used to abort execution. - /// The method is not supported on this platform. - /// The argument is null. - /// - /// The current thread is already running the method. + /// The method is not supported on this platform. + /// The argument is null. + /// + /// The current thread is already running the method. /// - /// The execution was aborted. + /// The execution was aborted. /// /// This method enables aborting arbitrary managed code in a non-cooperative manner by throwing an exception /// in the thread executing that code. While the exception may be caught by the code, it is re-thrown at the end diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ComTypes/IEnumerable.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ComTypes/IEnumerable.cs index bfe2ad30092cf6..b3ab4f4056b1ce 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ComTypes/IEnumerable.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ComTypes/IEnumerable.cs @@ -15,6 +15,6 @@ namespace System.Runtime.InteropServices.ComTypes internal interface IEnumerable { [DispId(-4)] - System.Collections.IEnumerator GetEnumerator(); + Collections.IEnumerator GetEnumerator(); } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs index e3293c6e12c541..9a334d044d5d77 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs @@ -235,7 +235,7 @@ public object GetOrCreateObjectForComInstance(IntPtr externalComObject, CreateOb /// The to be used as the wrapper for the external object /// Returns a managed object associated with the supplied external COM object. /// - /// If the instance already has an associated external object a will be thrown. + /// If the instance already has an associated external object a will be thrown. /// public object GetOrRegisterObjectForComInstance(IntPtr externalComObject, CreateObjectFlags flags, object wrapper) { @@ -256,7 +256,7 @@ public object GetOrRegisterObjectForComInstance(IntPtr externalComObject, Create /// in an unknown apartment state. If the supplied inner is not known to be a free-threaded instance then /// it is advised to not supply the inner. /// - /// If the instance already has an associated external object a will be thrown. + /// If the instance already has an associated external object a will be thrown. /// public object GetOrRegisterObjectForComInstance(IntPtr externalComObject, CreateObjectFlags flags, object wrapper, IntPtr inner) { @@ -315,7 +315,7 @@ internal static void CallReleaseObjects(ComWrappers? comWrappersImpl, IEnumerabl /// Instance to register /// /// This function can only be called a single time. Subsequent calls to this function will result - /// in a being thrown. + /// in a being thrown. /// /// Scenarios where this global instance may be used are: /// * Object tracking via the and flags. @@ -343,7 +343,7 @@ public static void RegisterForTrackerSupport(ComWrappers instance) /// Instance to register /// /// This function can only be called a single time. Subsequent calls to this function will result - /// in a being thrown. + /// in a being thrown. /// /// Scenarios where this global instance may be used are: /// * Usage of COM-related Marshal APIs diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumerableViewOfDispatch.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumerableViewOfDispatch.cs index d9d941138ca609..fa94eefcfb6a8d 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumerableViewOfDispatch.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumerableViewOfDispatch.cs @@ -6,7 +6,7 @@ namespace System.Runtime.InteropServices.CustomMarshalers { - internal sealed class EnumerableViewOfDispatch : ICustomAdapter, System.Collections.IEnumerable + internal sealed class EnumerableViewOfDispatch : ICustomAdapter, Collections.IEnumerable { // Reserved DISPID slot for getting an enumerator from an IDispatch-implementing COM interface. private const int DISPID_NEWENUM = -4; @@ -20,7 +20,7 @@ public EnumerableViewOfDispatch(object dispatch) private IDispatch Dispatch => (IDispatch)_dispatch; - public System.Collections.IEnumerator GetEnumerator() + public Collections.IEnumerator GetEnumerator() { Variant result; unsafe @@ -50,7 +50,7 @@ public System.Collections.IEnumerator GetEnumerator() } enumVariantPtr = Marshal.GetIUnknownForObject(enumVariant); - return (System.Collections.IEnumerator)EnumeratorToEnumVariantMarshaler.GetInstance(null).MarshalNativeToManaged(enumVariantPtr); + return (Collections.IEnumerator)EnumeratorToEnumVariantMarshaler.GetInstance(null).MarshalNativeToManaged(enumVariantPtr); } finally { diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorViewOfEnumVariant.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorViewOfEnumVariant.cs index a62fad1a0dc543..25f03f14133e97 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorViewOfEnumVariant.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/CustomMarshalers/EnumeratorViewOfEnumVariant.cs @@ -5,7 +5,7 @@ namespace System.Runtime.InteropServices.CustomMarshalers { - internal sealed class EnumeratorViewOfEnumVariant : ICustomAdapter, System.Collections.IEnumerator + internal sealed class EnumeratorViewOfEnumVariant : ICustomAdapter, Collections.IEnumerator { private readonly IEnumVARIANT _enumVariantObject; private bool _fetchedLastObject; diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/DynamicInterfaceCastableHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/DynamicInterfaceCastableHelpers.cs index da3cd7f1059e27..588ba04b139616 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/DynamicInterfaceCastableHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/InteropServices/DynamicInterfaceCastableHelpers.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Diagnostics; + namespace System.Runtime.InteropServices { /// @@ -10,7 +12,7 @@ namespace System.Runtime.InteropServices /// internal static class DynamicInterfaceCastableHelpers { - [Diagnostics.StackTraceHidden] + [StackTraceHidden] internal static bool IsInterfaceImplemented(IDynamicInterfaceCastable castable, RuntimeType interfaceType, bool throwIfNotImplemented) { bool isImplemented= castable.IsInterfaceImplemented(new RuntimeTypeHandle(interfaceType), throwIfNotImplemented); @@ -20,7 +22,7 @@ internal static bool IsInterfaceImplemented(IDynamicInterfaceCastable castable, return isImplemented; } - [Diagnostics.StackTraceHidden] + [StackTraceHidden] internal static RuntimeType? GetInterfaceImplementation(IDynamicInterfaceCastable castable, RuntimeType interfaceType) { RuntimeTypeHandle handle = castable.GetInterfaceImplementation(new RuntimeTypeHandle(interfaceType)); 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 f5650b4e1ff7b5..8e2596f994fd1a 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 @@ -133,7 +133,7 @@ public static void WriteByte(object ptr, int ofs, byte val) [RequiresDynamicCode("Marshalling code for the object might not be available")] public static void WriteInt16(object ptr, int ofs, short val) { - WriteValueSlow(ptr, ofs, val, Marshal.WriteInt16); + WriteValueSlow(ptr, ofs, val, WriteInt16); } [EditorBrowsable(EditorBrowsableState.Never)] @@ -141,7 +141,7 @@ public static void WriteInt16(object ptr, int ofs, short val) [RequiresDynamicCode("Marshalling code for the object might not be available")] public static void WriteInt32(object ptr, int ofs, int val) { - WriteValueSlow(ptr, ofs, val, Marshal.WriteInt32); + WriteValueSlow(ptr, ofs, val, WriteInt32); } [EditorBrowsable(EditorBrowsableState.Never)] @@ -149,7 +149,7 @@ public static void WriteInt32(object ptr, int ofs, int val) [RequiresDynamicCode("Marshalling code for the object might not be available")] public static void WriteInt64(object ptr, int ofs, long val) { - WriteValueSlow(ptr, ofs, val, Marshal.WriteInt64); + WriteValueSlow(ptr, ofs, val, WriteInt64); } /// diff --git a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs index 75ce9685828218..b3b05a381218c4 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Runtime/Loader/AssemblyLoadContext.CoreCLR.cs @@ -156,7 +156,7 @@ private static IntPtr ResolveUnmanagedDllUsingEvent(string unmanagedDllName, Ass { // If the load context is returned null, then the assembly was bound using the TPA binder // and we shall return reference to the "Default" binder. - loadContextForAssembly = AssemblyLoadContext.Default; + loadContextForAssembly = Default; } else { @@ -217,7 +217,7 @@ private static void StopAssemblyLoad(ref Guid activityId) /// private static void InitializeDefaultContext() { - _ = AssemblyLoadContext.Default; + _ = Default; } } } diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs index 38125e88795cd9..bd1e343398f9b9 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeHandles.cs @@ -312,7 +312,7 @@ internal RuntimeType GetRuntimeType() public ModuleHandle GetModuleHandle() { - return new ModuleHandle(RuntimeTypeHandle.GetModule(m_type)); + return new ModuleHandle(GetModule(m_type)); } [MethodImpl(MethodImplOptions.InternalCall)] @@ -350,7 +350,7 @@ internal struct IntroducedMethodEnumerator internal IntroducedMethodEnumerator(RuntimeType type) { - _handle = RuntimeTypeHandle.GetFirstIntroducedMethod(type); + _handle = GetFirstIntroducedMethod(type); _firstCall = true; } @@ -362,7 +362,7 @@ public bool MoveNext() } else if (_handle.Value != IntPtr.Zero) { - RuntimeTypeHandle.GetNextIntroducedMethod(ref _handle); + GetNextIntroducedMethod(ref _handle); } return !(_handle.Value == IntPtr.Zero); } @@ -457,7 +457,7 @@ internal static bool IsComObject(RuntimeType type, bool isGenericCOM) if (isGenericCOM) return type.TypeHandle.Value == typeof(__ComObject).TypeHandle.Value; - return RuntimeTypeHandle.CanCastTo(type, (RuntimeType)typeof(__ComObject)); + return CanCastTo(type, (RuntimeType)typeof(__ComObject)); #else return false; #endif @@ -803,7 +803,7 @@ public override bool Equals(object? obj) public static RuntimeMethodHandle FromIntPtr(IntPtr value) { var handle = new RuntimeMethodHandleInternal(value); - var methodInfo = new RuntimeMethodInfoStub(handle, RuntimeMethodHandle.GetLoaderAllocator(handle)); + var methodInfo = new RuntimeMethodInfoStub(handle, GetLoaderAllocator(handle)); return new RuntimeMethodHandle(methodInfo); } @@ -860,7 +860,7 @@ internal static partial Interop.BOOL IsCAVisibleFromDecoratedType( internal static MethodAttributes GetAttributes(IRuntimeMethodInfo method) { - MethodAttributes retVal = RuntimeMethodHandle.GetAttributes(method.Value); + MethodAttributes retVal = GetAttributes(method.Value); GC.KeepAlive(method); return retVal; } @@ -885,7 +885,7 @@ internal static string ConstructInstantiation(IRuntimeMethodInfo method, TypeNam internal static RuntimeType GetDeclaringType(IRuntimeMethodInfo method) { - RuntimeType type = RuntimeMethodHandle.GetDeclaringType(method.Value); + RuntimeType type = GetDeclaringType(method.Value); GC.KeepAlive(method); return type; } @@ -897,7 +897,7 @@ internal static int GetSlot(IRuntimeMethodInfo method) { Debug.Assert(method != null); - int slot = RuntimeMethodHandle.GetSlot(method.Value); + int slot = GetSlot(method.Value); GC.KeepAlive(method); return slot; } @@ -910,7 +910,7 @@ internal static int GetSlot(IRuntimeMethodInfo method) internal static string GetName(IRuntimeMethodInfo method) { - string name = RuntimeMethodHandle.GetName(method.Value); + string name = GetName(method.Value); GC.KeepAlive(method); return name; } @@ -965,7 +965,7 @@ internal static Type[] GetMethodInstantiationPublic(IRuntimeMethodInfo method) internal static bool HasMethodInstantiation(IRuntimeMethodInfo method) { - bool fRet = RuntimeMethodHandle.HasMethodInstantiation(method.Value); + bool fRet = HasMethodInstantiation(method.Value); GC.KeepAlive(method); return fRet; } @@ -981,7 +981,7 @@ internal static bool HasMethodInstantiation(IRuntimeMethodInfo method) internal static bool IsGenericMethodDefinition(IRuntimeMethodInfo method) { - bool fRet = RuntimeMethodHandle.IsGenericMethodDefinition(method.Value); + bool fRet = IsGenericMethodDefinition(method.Value); GC.KeepAlive(method); return fRet; } @@ -1157,7 +1157,7 @@ public bool Equals(RuntimeFieldHandle handle) public static RuntimeFieldHandle FromIntPtr(IntPtr value) { var handle = new RuntimeFieldHandleInternal(value); - var fieldInfo = new RuntimeFieldInfoStub(handle, RuntimeFieldHandle.GetLoaderAllocator(handle)); + var fieldInfo = new RuntimeFieldInfoStub(handle, GetLoaderAllocator(handle)); return new RuntimeFieldHandle(fieldInfo); } @@ -1275,7 +1275,7 @@ public bool Equals(ModuleHandle handle) public static bool operator !=(ModuleHandle left, ModuleHandle right) => !left.Equals(right); [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern IRuntimeMethodInfo GetDynamicMethod(System.Reflection.Emit.DynamicMethod method, RuntimeModule module, string name, byte[] sig, Resolver resolver); + internal static extern IRuntimeMethodInfo GetDynamicMethod(Reflection.Emit.DynamicMethod method, RuntimeModule module, string name, byte[] sig, Resolver resolver); [MethodImpl(MethodImplOptions.InternalCall)] internal static extern int GetToken(RuntimeModule module); diff --git a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.ActivatorCache.cs b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.ActivatorCache.cs index abf4f4afa4410f..d82daa26f0ccf4 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.ActivatorCache.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.ActivatorCache.cs @@ -11,7 +11,7 @@ internal sealed partial class RuntimeType { /// /// A cache which allows optimizing , - /// , and related APIs. + /// , and related APIs. /// private sealed unsafe class ActivatorCache { 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 872f9d08b1910e..12b85edffacb6f 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/RuntimeType.CoreCLR.cs @@ -1114,7 +1114,7 @@ private RuntimeType[] PopulateNestedClasses(Filter filter) { nestedType = moduleHandle.ResolveTypeHandle(tkNestedClasses[i]).GetRuntimeType(); } - catch (System.TypeLoadException) + catch (TypeLoadException) { // In a reflection emit scenario, we may have a token for a class which // has not been baked and hence cannot be loaded. @@ -1474,7 +1474,7 @@ private string ConstructName([NotNull] ref string? name, TypeNameFormatFlags for private T[] GetMemberList(ref MemberInfoCache? m_cache, MemberListType listType, string? name, CacheType cacheType) where T : MemberInfo { - MemberInfoCache existingCache = GetMemberCache(ref m_cache); + MemberInfoCache existingCache = GetMemberCache(ref m_cache); return existingCache.GetMemberList(listType, name, cacheType); } @@ -1721,54 +1721,54 @@ internal MethodInfo GetGenericMethodInfo(RuntimeMethodHandleInternal genericMeth internal RuntimeMethodInfo[] GetMethodList(MemberListType listType, string? name) { - return GetMemberList(ref m_methodInfoCache, listType, name, CacheType.Method); + return GetMemberList(ref m_methodInfoCache, listType, name, CacheType.Method); } internal RuntimeConstructorInfo[] GetConstructorList(MemberListType listType, string? name) { - return GetMemberList(ref m_constructorInfoCache, listType, name, CacheType.Constructor); + return GetMemberList(ref m_constructorInfoCache, listType, name, CacheType.Constructor); } internal RuntimePropertyInfo[] GetPropertyList(MemberListType listType, string? name) { - return GetMemberList(ref m_propertyInfoCache, listType, name, CacheType.Property); + return GetMemberList(ref m_propertyInfoCache, listType, name, CacheType.Property); } internal RuntimeEventInfo[] GetEventList(MemberListType listType, string? name) { - return GetMemberList(ref m_eventInfoCache, listType, name, CacheType.Event); + return GetMemberList(ref m_eventInfoCache, listType, name, CacheType.Event); } internal RuntimeFieldInfo[] GetFieldList(MemberListType listType, string? name) { - return GetMemberList(ref m_fieldInfoCache, listType, name, CacheType.Field); + return GetMemberList(ref m_fieldInfoCache, listType, name, CacheType.Field); } internal RuntimeType[] GetInterfaceList(MemberListType listType, string? name) { - return GetMemberList(ref m_interfaceCache, listType, name, CacheType.Interface); + return GetMemberList(ref m_interfaceCache, listType, name, CacheType.Interface); } internal RuntimeType[] GetNestedTypeList(MemberListType listType, string? name) { - return GetMemberList(ref m_nestedClassesCache, listType, name, CacheType.NestedType); + return GetMemberList(ref m_nestedClassesCache, listType, name, CacheType.NestedType); } internal MethodBase GetMethod(RuntimeType declaringType, RuntimeMethodHandleInternal method) { - GetMemberCache(ref m_methodInfoCache); + GetMemberCache(ref m_methodInfoCache); return m_methodInfoCache!.AddMethod(declaringType, method, CacheType.Method); } internal MethodBase GetConstructor(RuntimeType declaringType, RuntimeMethodHandleInternal constructor) { - GetMemberCache(ref m_constructorInfoCache); + GetMemberCache(ref m_constructorInfoCache); return m_constructorInfoCache!.AddMethod(declaringType, constructor, CacheType.Constructor); } internal FieldInfo GetField(RuntimeFieldHandleInternal field) { - GetMemberCache(ref m_fieldInfoCache); + GetMemberCache(ref m_fieldInfoCache); return m_fieldInfoCache!.AddField(field); } @@ -2395,7 +2395,7 @@ private static bool FilterApplyMethodBase( private IntPtr m_cache; internal IntPtr m_handle; - internal static readonly RuntimeType ValueType = (RuntimeType)typeof(System.ValueType); + internal static readonly RuntimeType ValueType = (RuntimeType)typeof(ValueType); private static readonly RuntimeType ObjectType = (RuntimeType)typeof(object); private static readonly RuntimeType StringType = (RuntimeType)typeof(string); @@ -2822,9 +2822,7 @@ public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(Dyn { MethodInfo methodInfo = candidates[j]; if (!System.DefaultBinder.CompareMethodSig(methodInfo, firstCandidate)) - { - throw new AmbiguousMatchException(); - } + throw ThrowHelper.GetAmbiguousMatchException(firstCandidate); } // All the methods have the exact same name and sig so return the most derived one. @@ -2878,10 +2876,10 @@ public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(Dyn if (types == null || types.Length == 0) { // no arguments + PropertyInfo firstCandidate = candidates[0]; + if (candidates.Count == 1) { - PropertyInfo firstCandidate = candidates[0]; - if (returnType is not null && !returnType.IsEquivalentTo(firstCandidate.PropertyType)) return null; @@ -2891,7 +2889,7 @@ public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(Dyn { if (returnType is null) // if we are here we have no args or property type to select over and we have more than one property with that name - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(firstCandidate); } } @@ -2920,7 +2918,7 @@ public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(Dyn if ((bindingAttr & eventInfo.BindingFlags) == eventInfo.BindingFlags) { if (match != null) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(match); match = eventInfo; } @@ -2950,7 +2948,7 @@ public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(Dyn if (match != null) { if (ReferenceEquals(fieldInfo.DeclaringType, match.DeclaringType)) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(match); if ((match.DeclaringType!.IsInterface) && (fieldInfo.DeclaringType!.IsInterface)) multipleStaticFieldMatches = true; @@ -2962,7 +2960,7 @@ public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(Dyn } if (multipleStaticFieldMatches && match!.DeclaringType!.IsInterface) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(match); return match; } @@ -2998,7 +2996,7 @@ public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(Dyn if (FilterApplyType(iface, bindingAttr, name, false, ns)) { if (match != null) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(match); match = iface; } @@ -3027,7 +3025,7 @@ public override InterfaceMapping GetInterfaceMap([DynamicallyAccessedMembers(Dyn if (FilterApplyType(nestedType, bindingAttr, name, false, ns)) { if (match != null) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(match); match = nestedType; } @@ -3395,7 +3393,7 @@ public override unsafe bool IsEnum if (th.IsTypeDesc) return IsSubclassOf(typeof(Enum)); - bool isEnum = th.AsMethodTable()->ParentMethodTable == System.Runtime.CompilerServices.TypeHandle.TypeHandleOf().AsMethodTable(); + bool isEnum = th.AsMethodTable()->ParentMethodTable == Runtime.CompilerServices.TypeHandle.TypeHandleOf().AsMethodTable(); GC.KeepAlive(this); return isEnum; } @@ -3409,7 +3407,7 @@ internal unsafe bool IsActualEnum { TypeHandle th = GetNativeTypeHandle(); - bool isEnum = !th.IsTypeDesc && th.AsMethodTable()->ParentMethodTable == System.Runtime.CompilerServices.TypeHandle.TypeHandleOf().AsMethodTable(); + bool isEnum = !th.IsTypeDesc && th.AsMethodTable()->ParentMethodTable == Runtime.CompilerServices.TypeHandle.TypeHandleOf().AsMethodTable(); GC.KeepAlive(this); return isEnum; } @@ -3419,7 +3417,7 @@ internal unsafe bool IsDelegate() { TypeHandle th = GetNativeTypeHandle(); - bool isDelegate = !th.IsTypeDesc && th.AsMethodTable()->ParentMethodTable == System.Runtime.CompilerServices.TypeHandle.TypeHandleOf().AsMethodTable(); + bool isDelegate = !th.IsTypeDesc && th.AsMethodTable()->ParentMethodTable == Runtime.CompilerServices.TypeHandle.TypeHandleOf().AsMethodTable(); GC.KeepAlive(this); return isDelegate; } @@ -3501,7 +3499,7 @@ internal RuntimeType[] GetGenericArgumentsInternal() public override Type[] GetGenericArguments() { Type[] types = GetRootElementType().TypeHandle.GetInstantiationPublic(); - return types ?? Type.EmptyTypes; + return types ?? EmptyTypes; } [RequiresUnreferencedCode("If some of the generic arguments are annotated (either with DynamicallyAccessedMembersAttribute, or generic constraints), trimming can't validate that the requirements of those annotations are met.")] @@ -3559,7 +3557,7 @@ public override Type MakeGenericType(Type[] instantiation) if (foundSigType) return new SignatureConstructedGenericType(this, instantiation); - return System.Reflection.Emit.TypeBuilderInstantiation.MakeGenericType(this, (Type[])(instantiation.Clone())); + return Reflection.Emit.TypeBuilderInstantiation.MakeGenericType(this, (Type[])(instantiation.Clone())); } SanityCheckGenericArguments(instantiationRuntimeType, genericParameters); @@ -3598,7 +3596,7 @@ public override Type[] GetGenericParameterConstraints() throw new InvalidOperationException(SR.Arg_NotGenericParameter); Type[] constraints = new RuntimeTypeHandle(this).GetConstraints(); - return constraints ?? Type.EmptyTypes; + return constraints ?? EmptyTypes; } #endregion diff --git a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs index 1ef0563e7ebd06..431c2f724a02ba 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs @@ -1294,7 +1294,7 @@ internal static void CheckStringLength(uint length) #endif [Intrinsic] - [MethodImplAttribute(MethodImplOptions.InternalCall)] + [MethodImpl(MethodImplOptions.InternalCall)] internal static extern IntPtr NextCallReturnAddress(); } // class StubHelpers } diff --git a/src/coreclr/System.Private.CoreLib/src/System/Text/StringBuilder.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Text/StringBuilder.CoreCLR.cs index 40973d0e30e950..4988ae32548518 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Text/StringBuilder.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Text/StringBuilder.CoreCLR.cs @@ -12,7 +12,7 @@ private int GetReplaceBufferCapacity(int requiredCapacity) { // This function assumes that required capacity will be less // than the max capacity of the StringBuilder - Diagnostics.Debug.Assert(requiredCapacity <= m_MaxCapacity); + Debug.Assert(requiredCapacity <= m_MaxCapacity); int newCapacity = Capacity; // Round the current capacity to the nearest multiple of 2 diff --git a/src/coreclr/System.Private.CoreLib/src/System/Threading/Interlocked.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Threading/Interlocked.CoreCLR.cs index 2e683dcf73c8ac..6ee5eb20c8f646 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Threading/Interlocked.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Threading/Interlocked.CoreCLR.cs @@ -60,22 +60,6 @@ public static long Decrement(ref long location) => [MethodImpl(MethodImplOptions.InternalCall)] public static extern long Exchange(ref long location1, long value); - /// Sets a single-precision floating point number to a specified value and returns the original value, as an atomic operation. - /// The variable to set to the specified value. - /// The value to which the parameter is set. - /// The original value of . - /// The address of location1 is a null pointer. - [MethodImpl(MethodImplOptions.InternalCall)] - public static extern float Exchange(ref float location1, float value); - - /// Sets a double-precision floating point number to a specified value and returns the original value, as an atomic operation. - /// The variable to set to the specified value. - /// The value to which the parameter is set. - /// The original value of . - /// The address of location1 is a null pointer. - [MethodImpl(MethodImplOptions.InternalCall)] - public static extern double Exchange(ref double location1, double value); - /// Sets an object to the specified value and returns a reference to the original object, as an atomic operation. /// The variable to set to the specified value. /// The value to which the parameter is set. @@ -122,24 +106,6 @@ public static T Exchange([NotNullIfNotNull(nameof(value))] ref T location1, T [MethodImpl(MethodImplOptions.InternalCall)] public static extern long CompareExchange(ref long location1, long value, long comparand); - /// Compares two single-precision floating point numbers for equality and, if they are equal, replaces the first value. - /// The destination, whose value is compared with and possibly replaced. - /// The value that replaces the destination value if the comparison results in equality. - /// The value that is compared to the value at . - /// The original value in . - /// The address of is a null pointer. - [MethodImpl(MethodImplOptions.InternalCall)] - public static extern float CompareExchange(ref float location1, float value, float comparand); - - /// Compares two double-precision floating point numbers for equality and, if they are equal, replaces the first value. - /// The destination, whose value is compared with and possibly replaced. - /// The value that replaces the destination value if the comparison results in equality. - /// The value that is compared to the value at . - /// The original value in . - /// The address of is a null pointer. - [MethodImpl(MethodImplOptions.InternalCall)] - public static extern double CompareExchange(ref double location1, double value, double comparand); - /// Compares two objects for reference equality and, if they are equal, replaces the first object. /// The destination object that is compared by reference with and possibly replaced. /// The object that replaces the destination object if the reference comparison results in equality. @@ -208,25 +174,7 @@ public static long Read(ref long location) => CompareExchange(ref location, 0, 0); #endregion - #region MemoryBarrier - /// - /// Synchronizes memory access as follows: - /// The processor that executes the current thread cannot reorder instructions in such a way that memory accesses before - /// the call to execute after memory accesses that follow the call to . - /// - [Intrinsic] - [MethodImpl(MethodImplOptions.InternalCall)] - public static extern void MemoryBarrier(); - - /// - /// Synchronizes memory access as follows: - /// The processor that executes the current thread cannot reorder instructions in such a way that memory reads before - /// the call to execute after memory accesses that follow the call to . - /// - [Intrinsic] - [MethodImpl(MethodImplOptions.InternalCall)] - internal static extern void ReadMemoryBarrier(); - + #region MemoryBarrierProcessWide [LibraryImport(RuntimeHelpers.QCall, EntryPoint = "Interlocked_MemoryBarrierProcessWide")] private static partial void _MemoryBarrierProcessWide(); diff --git a/src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs index 7a52db2be2de64..64ba59f672ec09 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs @@ -248,7 +248,7 @@ private bool SetApartmentStateUnchecked(ApartmentState state, bool throwOnError) // Once we CoUninitialize the thread, the OS will still // report the thread as implicitly in the MTA if any // other thread in the process is CoInitialized. - if ((state == System.Threading.ApartmentState.Unknown) && (retState == System.Threading.ApartmentState.MTA)) + if ((state == ApartmentState.Unknown) && (retState == ApartmentState.MTA)) { return true; } 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 fe4b8622b56336..b858949e73eada 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Type.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Type.CoreCLR.cs @@ -5,6 +5,7 @@ using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; +using System.Security; using StackCrawlMark = System.Threading.StackCrawlMark; namespace System @@ -22,7 +23,7 @@ public bool IsInterface } [RequiresUnreferencedCode("The type might be removed")] - [System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod + [DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod public static Type? GetType(string typeName, bool throwOnError, bool ignoreCase) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -31,7 +32,7 @@ public bool IsInterface } [RequiresUnreferencedCode("The type might be removed")] - [System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod + [DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod public static Type? GetType(string typeName, bool throwOnError) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -40,7 +41,7 @@ public bool IsInterface } [RequiresUnreferencedCode("The type might be removed")] - [System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod + [DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod public static Type? GetType(string typeName) { StackCrawlMark stackMark = StackCrawlMark.LookForMyCaller; @@ -48,7 +49,7 @@ public bool IsInterface } [RequiresUnreferencedCode("The type might be removed")] - [System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod + [DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod public static Type? GetType( string typeName, Func? assemblyResolver, @@ -60,7 +61,7 @@ public bool IsInterface } [RequiresUnreferencedCode("The type might be removed")] - [System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod + [DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod public static Type? GetType( string typeName, Func? assemblyResolver, @@ -74,7 +75,7 @@ public bool IsInterface } [RequiresUnreferencedCode("The type might be removed")] - [System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod + [DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod public static Type? GetType( string typeName, Func? assemblyResolver, diff --git a/src/coreclr/System.Private.CoreLib/src/System/TypedReference.CoreCLR.cs b/src/coreclr/System.Private.CoreLib/src/System/TypedReference.CoreCLR.cs index 46b9d2bd9fb2e5..25538c0a0b4a39 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/TypedReference.CoreCLR.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/TypedReference.CoreCLR.cs @@ -6,10 +6,11 @@ using System.Diagnostics; using System.Runtime.CompilerServices; +using System.Runtime.Versioning; namespace System { - [System.Runtime.Versioning.NonVersionable] // This only applies to field layout + [NonVersionable] // This only applies to field layout public ref partial struct TypedReference { private readonly ref byte _value; diff --git a/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs b/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs index 880de9ac6af953..cc13e37e083f01 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/ValueType.cs @@ -17,7 +17,7 @@ namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public abstract class ValueType { [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", diff --git a/src/coreclr/System.Private.CoreLib/src/System/Variant.cs b/src/coreclr/System.Private.CoreLib/src/System/Variant.cs index 9b7f27f8d10929..0f55a7ef6a0224 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/Variant.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/Variant.cs @@ -67,8 +67,8 @@ internal struct Variant internal const int ArrayBitMask = 0x10000; internal static Variant Empty => default; - internal static Variant Missing => new Variant(Variant.CV_MISSING, Type.Missing, 0); - internal static Variant DBNull => new Variant(Variant.CV_NULL, System.DBNull.Value, 0); + internal static Variant Missing => new Variant(CV_MISSING, Type.Missing, 0); + internal static Variant DBNull => new Variant(CV_NULL, System.DBNull.Value, 0); // // Native Methods diff --git a/src/coreclr/clrdefinitions.cmake b/src/coreclr/clrdefinitions.cmake index b5a43f5057a47b..172d68e8964777 100644 --- a/src/coreclr/clrdefinitions.cmake +++ b/src/coreclr/clrdefinitions.cmake @@ -185,9 +185,9 @@ endif(FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION) add_definitions(-DFEATURE_SVR_GC) add_definitions(-DFEATURE_SYMDIFF) add_compile_definitions(FEATURE_TIERED_COMPILATION) -if (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64) +if (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_LOONGARCH64) add_compile_definitions(FEATURE_ON_STACK_REPLACEMENT) -endif (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64) +endif (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_ARM64 OR CLR_CMAKE_TARGET_ARCH_LOONGARCH64) add_compile_definitions(FEATURE_PGO) if (CLR_CMAKE_TARGET_WIN32) add_definitions(-DFEATURE_TYPEEQUIVALENCE) diff --git a/src/coreclr/crossgen-corelib.proj b/src/coreclr/crossgen-corelib.proj index 0ee3d5185c1934..747864a0047a63 100644 --- a/src/coreclr/crossgen-corelib.proj +++ b/src/coreclr/crossgen-corelib.proj @@ -122,7 +122,7 @@ - + diff --git a/src/coreclr/dlls/mscorpe/ceefilegenwriter.cpp b/src/coreclr/dlls/mscorpe/ceefilegenwriter.cpp index e6135077675039..b6cc342c741d80 100644 --- a/src/coreclr/dlls/mscorpe/ceefilegenwriter.cpp +++ b/src/coreclr/dlls/mscorpe/ceefilegenwriter.cpp @@ -180,24 +180,11 @@ inline IMAGE_SYMBOL* GetSymbolEntry(IMAGE_SYMBOL* pHead, SIZE_T idx) } //***************************************************************************** -// To get a new instance, call CreateNewInstance() or CreateNewInstanceEx() instead of new +// To get a new instance, call CreateNewInstance() instead of new //***************************************************************************** -HRESULT CeeFileGenWriter::CreateNewInstance(CCeeGen *pCeeFileGenFrom, - CeeFileGenWriter* & pGenWriter, +HRESULT CeeFileGenWriter::CreateNewInstance(CeeFileGenWriter* & pGenWriter, DWORD createFlags) -{ - return CreateNewInstanceEx(pCeeFileGenFrom, pGenWriter, createFlags); -} - -// -// Seed file is used as the base file. The new file data will be "appended" to the seed file -// - -HRESULT CeeFileGenWriter::CreateNewInstanceEx(CCeeGen *pCeeFileGenFrom, - CeeFileGenWriter* & pGenWriter, - DWORD createFlags, - LPCWSTR seedFileName) { HRESULT hr = S_OK; ULONG preallocatedOffset = 0; @@ -213,10 +200,7 @@ HRESULT CeeFileGenWriter::CreateNewInstanceEx(CCeeGen *pCeeFileGenFrom, if (pPEWriter == NULL) IfFailGo(E_OUTOFMEMORY); - //workaround - //What's really the correct thing to be doing here? - //HRESULT hr = pPEWriter->Init(pCeeFileGenFrom ? pCeeFileGenFrom->getPESectionMan() : NULL); - hr = pPEWriter->Init(NULL, createFlags, seedFileName); + hr = pPEWriter->Init(NULL, createFlags); IfFailGo(hr); //Create the general PEWriter. @@ -224,16 +208,13 @@ HRESULT CeeFileGenWriter::CreateNewInstanceEx(CCeeGen *pCeeFileGenFrom, hr = pPrivateGenWriter->Init(); // base class member to finish init IfFailGo(hr); - if (!seedFileName) // Use base file's preferred base (if present) + if (pPEWriter->isPE32()) { - if (pPEWriter->isPE32()) - { - pPrivateGenWriter->setImageBase((DWORD) CEE_IMAGE_BASE_32); // use same default as linker - } - else - { - pPrivateGenWriter->setImageBase64((ULONGLONG) CEE_IMAGE_BASE_64); // use same default as linker - } + pPrivateGenWriter->setImageBase((DWORD) CEE_IMAGE_BASE_32); // use same default as linker + } + else + { + pPrivateGenWriter->setImageBase64((ULONGLONG) CEE_IMAGE_BASE_64); // use same default as linker } pPrivateGenWriter->setSubsystem(IMAGE_SUBSYSTEM_WINDOWS_CUI, CEE_IMAGE_SUBSYSTEM_MAJOR_VERSION, CEE_IMAGE_SUBSYSTEM_MINOR_VERSION); @@ -247,11 +228,6 @@ HRESULT CeeFileGenWriter::CreateNewInstanceEx(CCeeGen *pCeeFileGenFrom, hr = pPrivateGenWriter->allocateCorHeader(); // get COR header near front IfFailGo(hr); - //If we were passed a CCeeGen at the beginning, copy it's data now. - if (pCeeFileGenFrom) { - pCeeFileGenFrom->cloneInstance((CCeeGen*)pPrivateGenWriter); - } - hr = pPrivateGenWriter->getSectionCreate(".text0", sdExecute, &corHeaderSection); IfFailGo(hr); preallocatedOffset = corHeaderSection->dataLen(); diff --git a/src/coreclr/dlls/mscorpe/iceefilegen.cpp b/src/coreclr/dlls/mscorpe/iceefilegen.cpp index 6c40d9699fce91..152fe9b3fcaf91 100644 --- a/src/coreclr/dlls/mscorpe/iceefilegen.cpp +++ b/src/coreclr/dlls/mscorpe/iceefilegen.cpp @@ -34,42 +34,19 @@ HRESULT ICeeFileGen::CreateCeeFile (HCEEFILE *ceeFile) } HRESULT ICeeFileGen::CreateCeeFileEx (HCEEFILE *ceeFile, DWORD createFlags) -{ - return CreateCeeFileEx2(ceeFile, createFlags, NULL); -} - -// -// Seed file is used as the base file. The new file data will be "appended" to the seed file -// - -HRESULT ICeeFileGen::CreateCeeFileEx2 (HCEEFILE *ceeFile, DWORD createFlags, LPCWSTR seedFileName) { if (!ceeFile) return E_POINTER; CeeFileGenWriter *gen = NULL; HRESULT hr; - IfFailRet(CeeFileGenWriter::CreateNewInstanceEx(NULL, gen, createFlags, seedFileName)); + IfFailRet(CeeFileGenWriter::CreateNewInstance(gen, createFlags)); TESTANDRETURN(gen != NULL, E_OUTOFMEMORY); *ceeFile = gen; return S_OK; } -HRESULT ICeeFileGen::CreateCeeFileFromICeeGen(ICeeGenInternal *pICeeGen, HCEEFILE *ceeFile, DWORD createFlags) -{ - if (!ceeFile) - return E_POINTER; - CCeeGen *genFrom = reinterpret_cast(pICeeGen); - CeeFileGenWriter *gen = NULL; - HRESULT hr = CeeFileGenWriter::CreateNewInstance(genFrom, gen, createFlags); - if (FAILED(hr)) - return hr; - TESTANDRETURN(gen != NULL, E_OUTOFMEMORY); - *ceeFile = gen; - return S_OK; -} - HRESULT ICeeFileGen::DestroyCeeFile(HCEEFILE *ceeFile) { if (!ceeFile) @@ -262,12 +239,6 @@ HRESULT ICeeFileGen::SetSubsystem(HCEEFILE ceeFile, DWORD subsystem, DWORD major return S_OK; } -HRESULT ICeeFileGen::GetIMapTokenIface(HCEEFILE ceeFile, IMetaDataEmit *emitter, IUnknown **pIMapToken) -{ - _ASSERTE(!"This is an obsolete function!"); - return E_NOTIMPL; -} - HRESULT ICeeFileGen::GetMethodRVA(HCEEFILE ceeFile, ULONG codeOffset, ULONG *codeRVA) { TESTANDRETURNARG(ceeFile != 0); @@ -394,25 +365,6 @@ HRESULT ICeeFileGen::EmitMetaDataAt (HCEEFILE ceeFile, IMetaDataEmit *emitter, H return(gen->emitMetaData(emitter, sec, offset, buffer, buffLen)); } -HRESULT ICeeFileGen::GetIMapTokenIfaceEx(HCEEFILE ceeFile, IMetaDataEmit *emitter, IUnknown **pIMapToken) -{ - TESTANDRETURNPOINTER(ceeFile); - TESTANDRETURNPOINTER(pIMapToken); - - CeeFileGenWriter *gen = reinterpret_cast(ceeFile); - return gen->getMapTokenIface(pIMapToken); -} - -HRESULT ICeeFileGen::AddNotificationHandler(HCEEFILE ceeFile, - IUnknown *pHandler) -{ - TESTANDRETURNPOINTER(ceeFile); - TESTANDRETURNPOINTER(pHandler); - - CeeFileGenWriter *gen = reinterpret_cast(ceeFile); - return gen->addNotificationHandler(pHandler); -} - HRESULT ICeeFileGen::SetManifestEntry(HCEEFILE ceeFile, ULONG size, ULONG offset) { TESTANDRETURNPOINTER(ceeFile); diff --git a/src/coreclr/dlls/mscorpe/pewriter.cpp b/src/coreclr/dlls/mscorpe/pewriter.cpp index 2f40d3cd5b5939..a9f7a8fddf593e 100644 --- a/src/coreclr/dlls/mscorpe/pewriter.cpp +++ b/src/coreclr/dlls/mscorpe/pewriter.cpp @@ -686,41 +686,7 @@ HRESULT PEWriterSection::applyRelocs(IMAGE_NT_HEADERS * pNtHeaders, } /******************************************************************/ - -PESeedSection::PESeedSection(PEDecoder * peDecoder, - IMAGE_SECTION_HEADER * seedSection) - : PEWriterSection((const char *)seedSection->Name, - VAL32(seedSection->Characteristics), - VAL32(seedSection->SizeOfRawData), - 0), - m_pSeedFileDecoder(peDecoder), - m_pSeedSectionHeader(seedSection) -{ - m_baseRVA = VAL32(seedSection->VirtualAddress); -} - -HRESULT PESeedSection::write(HANDLE file) { - ULONG sizeOfSection = VAL32(m_pSeedSectionHeader->SizeOfRawData); - LPCVOID sectionData = PBYTE(m_pSeedFileDecoder->GetBase()) + m_pSeedSectionHeader->PointerToRawData; - - DWORD dwWritten = 0; - if (!WriteFile(file, sectionData, sizeOfSection, &dwWritten, NULL)) { - return HRESULT_FROM_GetLastError(); - } - _ASSERTE(dwWritten == sizeOfSection); - return S_OK; -} - -unsigned PESeedSection::writeMem(void ** pMem) { - ULONG sizeOfSection = VAL32(m_pSeedSectionHeader->SizeOfRawData); - LPCVOID sectionData = PBYTE(m_pSeedFileDecoder->GetBase()) + m_pSeedSectionHeader->PointerToRawData; - - COPY_AND_ADVANCE(*pMem, sectionData, sizeOfSection); - return sizeOfSection; -} - -/******************************************************************/ -HRESULT PEWriter::Init(PESectionMan *pFrom, DWORD createFlags, LPCWSTR seedFileName) +HRESULT PEWriter::Init(PESectionMan *pFrom, DWORD createFlags) { if (pFrom) *(PESectionMan*)this = *pFrom; @@ -878,103 +844,12 @@ HRESULT PEWriter::Init(PESectionMan *pFrom, DWORD createFlags, LPCWSTR seedFileN m_file = INVALID_HANDLE_VALUE; - // - // Seed file - // - - m_hSeedFile = INVALID_HANDLE_VALUE; - m_hSeedFileMap = INVALID_HANDLE_VALUE; - m_pSeedFileDecoder = NULL; - m_iSeedSections = 0; - m_pSeedSectionToAdd = NULL; - - if (seedFileName) - { - HandleHolder hFile (WszCreateFile(seedFileName, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, - NULL)); - - if (hFile == INVALID_HANDLE_VALUE) - return HRESULT_FROM_GetLastError(); - - MapViewHolder hMapFile (WszCreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL)); - DWORD dwFileLen = SafeGetFileSize(hFile, 0); - if (dwFileLen == 0xffffffff) - return HRESULT_FROM_GetLastError(); - - if (hMapFile == NULL) - return HRESULT_FROM_GetLastError(); - - BYTE * baseFileView = (BYTE*) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0); - - PEDecoder * pPEDecoder = new (nothrow) PEDecoder(baseFileView, (COUNT_T)dwFileLen); - if (pPEDecoder == NULL) return E_OUTOFMEMORY; - - if (pPEDecoder->Has32BitNTHeaders()) - { - if ((createFlags & ICEE_CREATE_FILE_PE32) == 0) - return E_FAIL; - - setImageBase32(DWORD(size_t(pPEDecoder->GetPreferredBase()))); - } - else - { - if ((createFlags & ICEE_CREATE_FILE_PE64) == 0) - return E_FAIL; - - setImageBase64(UINT64((intptr_t) pPEDecoder->GetPreferredBase())); - } - - setFileAlignment (VAL32(pPEDecoder->GetFileAlignment())); - setSectionAlignment(VAL32(pPEDecoder->GetSectionAlignment())); - - hFile.SuppressRelease(); - hMapFile.SuppressRelease(); - - m_hSeedFile = hFile; - m_hSeedFileMap = hMapFile; - m_pSeedFileDecoder = pPEDecoder; - -#ifdef HOST_64BIT - m_pSeedFileNTHeaders = pPEDecoder->GetNTHeaders64(); -#else - m_pSeedFileNTHeaders = pPEDecoder->GetNTHeaders32(); -#endif - - // Add the seed sections - - m_pSeedSections = m_pSeedFileDecoder->FindFirstSection(); - - m_pSeedSectionToAdd = m_pSeedSections; - m_iSeedSections = m_pSeedFileDecoder->GetNumberOfSections(); - - for (unsigned i = 0; i < m_iSeedSections; m_pSeedSectionToAdd++, i++) { - PESection * dummy; - getSectionCreate((const char *)(m_pSeedSectionToAdd->Name), - VAL32(m_pSeedSectionToAdd->Characteristics), - &dummy); - } - - m_pSeedSectionToAdd = NULL; - } - return S_OK; } /******************************************************************/ HRESULT PEWriter::Cleanup() { - if (m_hSeedFile != INVALID_HANDLE_VALUE) - { - CloseHandle(m_hSeedFile); - CloseHandle(m_hSeedFileMap); - delete m_pSeedFileDecoder; - } - if (isPE32()) { delete ntHeaders32(); @@ -993,43 +868,10 @@ HRESULT PEWriter::Cleanup() { return PESectionMan::Cleanup(); } -PESection* PEWriter::getSection(const char* name) -{ - int len = (int)strlen(name); - - // the section name can be at most 8 characters including the null. - if (len < 8) - len++; - else - len = 8; - - // dbPrintf(("looking for section %s\n", name)); - // Skip over the seed sections - - for(PESection** cur = sectStart+m_iSeedSections; cur < sectCur; cur++) { - // dbPrintf(("searching section %s\n", (*cur)->m_ame)); - if (strncmp((*cur)->m_name, name, len) == 0) { - // dbPrintf(("found section %s\n", (*cur)->m_name)); - return(*cur); - } - } - return(0); -} - HRESULT PEWriter::newSection(const char* name, PESection **section, unsigned flags, unsigned estSize, unsigned estRelocs) { - if (m_pSeedSectionToAdd) { - _ASSERTE(strcmp((const char *)(m_pSeedSectionToAdd->Name), name) == 0 && - VAL32(m_pSeedSectionToAdd->Characteristics) == flags); - - PESeedSection * ret = new (nothrow) PESeedSection(m_pSeedFileDecoder, m_pSeedSectionToAdd); - *section = ret; - TESTANDRETURNMEMORY(ret); - return S_OK; - } - PEWriterSection * ret = new (nothrow) PEWriterSection(name, flags, estSize, estRelocs); *section = ret; TESTANDRETURNMEMORY(ret); @@ -1165,15 +1007,13 @@ class SectionNameSorter : protected CQuickSort entry * m_entries; PEWriterSection ** m_sections; unsigned m_count; - unsigned m_seedCount; public: - SectionNameSorter(entry *entries, PEWriterSection ** sections, int count, unsigned seedSections) + SectionNameSorter(entry *entries, PEWriterSection ** sections, int count) : CQuickSort(entries, count), m_entries(entries), m_sections(sections), - m_count(unsigned(count)), - m_seedCount(seedSections) + m_count(unsigned(count)) {} // Sorts the entries according to alphabetical + numerical order @@ -1183,16 +1023,6 @@ class SectionNameSorter : protected CQuickSort PEWriterSection * firstSection = m_sections[first->arrayIndex]; PEWriterSection * secondSection = m_sections[second->arrayIndex]; - // Seed sections are always at the start, in the order they were - // added to the PEWriter - - if (firstSection->isSeedSection() || secondSection->isSeedSection()) { - if (firstSection->isSeedSection() && secondSection->isSeedSection()) - return first->arrayIndex - second->arrayIndex; - - return firstSection->isSeedSection() ? -1 : 1; - } - // Sort the names int lenDiff = first->nameLength - second->nameLength; @@ -1225,11 +1055,7 @@ class SectionNameSorter : protected CQuickSort for (unsigned i = 1; i < m_count; i++, ePrev = e, e++) { - // Seed sections should stay at the front - _ASSERTE(i >= m_seedCount || i == e->arrayIndex); - - if (!m_sections[ePrev->arrayIndex]->isSeedSection() && - (ePrev->nameLength == e->nameLength) && + if ((ePrev->nameLength == e->nameLength) && strncmp(ePrev->name, e->name, e->nameLength) == 0) { continue; @@ -1317,7 +1143,7 @@ HRESULT PEWriter::linkSortSections(entry * entries, // Sort the entries according to alphabetical + numerical order // - SectionNameSorter sorter(entries, getSectStart(), int(e - entries), m_iSeedSections); + SectionNameSorter sorter(entries, getSectStart(), int(e - entries)); *piUniqueSections = sorter.SortSections(); *piEntries = unsigned(e - entries); @@ -1367,7 +1193,6 @@ HRESULT PEWriter::linkSortHeaders(entry * entries, unsigned iEntries, unsigned i for (entry * e = entries ; e < entriesEnd; e++) { if (ePrev != NULL - && !getSectStart()[ePrev->arrayIndex]->isSeedSection() && e->nameLength == ePrev->nameLength && strncmp(e->name, ePrev->name, e->nameLength) == 0) { @@ -1433,10 +1258,6 @@ HRESULT PEWriter::linkPlaceSections(entry * entries, unsigned iEntries) entry * e = entries + VAL32(h->FirstEntryIndex); PEWriterSection *s = getSectStart()[e->arrayIndex]; - if (s->isSeedSection()) { - virtualPos = s->getBaseRVA(); - } - h->VirtualAddress = VAL32(virtualPos); h->PointerToRawData = VAL32(filePos); @@ -1501,11 +1322,6 @@ HRESULT PEWriter::linkPlaceSections(entry * entries, unsigned iEntries) void PEWriter::setSectionIndex(IMAGE_SECTION_HEADER * h, unsigned sectionIndex) { - if (getSectStart()[sectionIndex]->isSeedSection()) { - h->SectionIndex = VAL32(sectionIndex); - return; - } - // // Reserve some dummy "array index" values for special sections // at the start of the image (after the seed sections) @@ -1523,7 +1339,7 @@ void PEWriter::setSectionIndex(IMAGE_SECTION_HEADER * h, unsigned sectionIndex) } else if (strcmp((char *) h->Name, *s) == 0) { - h->SectionIndex = VAL32(m_iSeedSections + DWORD(s - SpecialNames)); + h->SectionIndex = VAL32(DWORD(s - SpecialNames)); break; } } @@ -1598,17 +1414,6 @@ HRESULT PEWriter::link() { virtualPos = roundUp(filePos, VAL32(m_ntHeaders->OptionalHeader.SectionAlignment)); - if (m_hSeedFile != INVALID_HANDLE_VALUE) { - // We do not support relocating/sliding down the seed sections - if (filePos > VAL32(m_pSeedSections->VirtualAddress) || - virtualPos > VAL32(m_pSeedSections->VirtualAddress)) - return E_FAIL; - - if (virtualPos < VAL32(m_pSeedSections->VirtualAddress)) { - virtualPos = VAL32(m_pSeedSections->VirtualAddress); - } - } - // Now finally assign RVAs to the sections IfFailRet(linkPlaceSections(entries, iEntries)); @@ -2014,8 +1819,6 @@ UINT64 PEWriter::getImageBase64() void PEWriter::setImageBase32(DWORD imageBase) { - _ASSERTE(m_hSeedFile == INVALID_HANDLE_VALUE); - _ASSERTE(isPE32()); ntHeaders32()->OptionalHeader.ImageBase = VAL32(imageBase); } diff --git a/src/coreclr/dlls/mscorpe/pewriter.h b/src/coreclr/dlls/mscorpe/pewriter.h index 11bba04a71b3f0..089f624bdaa5bb 100644 --- a/src/coreclr/dlls/mscorpe/pewriter.h +++ b/src/coreclr/dlls/mscorpe/pewriter.h @@ -28,12 +28,9 @@ class PEWriter : public PESectionMan public: // See ICeeFileGen.h for definition of createFlags - HRESULT Init(PESectionMan *pFrom, DWORD createFlags, LPCWSTR seedFileName = NULL); + HRESULT Init(PESectionMan *pFrom, DWORD createFlags); HRESULT Cleanup(); - // Finds section with given name. returns 0 if not found - virtual PESection* getSection(const char* name); - // Create a new section virtual HRESULT newSection(const char* name, PESection **section, unsigned flags=sdNone, unsigned estSize=0x10000, @@ -118,17 +115,6 @@ class PEWriter : public PESectionMan HANDLE m_file; - // "Seed" file information. The new file data will be "appended" to the seed file - // These are valid only if m_hSeedFile is valid - - HANDLE m_hSeedFile; - HANDLE m_hSeedFileMap; - PEDecoder * m_pSeedFileDecoder; - IMAGE_NT_HEADERS * m_pSeedFileNTHeaders; - unsigned m_iSeedSections; - IMAGE_SECTION_HEADER*m_pSeedSections; - IMAGE_SECTION_HEADER*m_pSeedSectionToAdd; // used only by newSection() - PEWriterSection **getSectStart() { return (PEWriterSection**)sectStart; } @@ -221,73 +207,13 @@ class PEWriterSection : public PESection { virtual HRESULT write (HANDLE file); virtual unsigned writeMem (void ** pMem); - virtual bool isSeedSection() { return false; } - -}; - -// This is for sections from the seed file. Their order needs to be maintained and -// they need to be written to the output file. - -class PESeedSection : public PEWriterSection { - -public: - - PESeedSection(PEDecoder * peDecoder, IMAGE_SECTION_HEADER * seedSection); - - // PESection methods - - unsigned dataLen() { return m_pSeedSectionHeader->SizeOfRawData; } - HRESULT applyRelocs(CeeGenTokenMapper *pTokenMapper) { return S_OK; } - char* getBlock(unsigned len, unsigned align) { _ASSERTE(!"PESeedSection"); return NULL; } - HRESULT truncate(unsigned newLen) { _ASSERTE(!"PESeedSection"); return E_FAIL; } - void writeSectReloc(unsigned val, CeeSection& relativeTo, - CeeSectionRelocType reloc, - CeeSectionRelocExtra *extra) { _ASSERTE(!"PESeedSection"); return; } - HRESULT addSectReloc(unsigned offset, CeeSection& relativeTo, - CeeSectionRelocType reloc, - CeeSectionRelocExtra *extra) { _ASSERTE(!"PESeedSection"); return E_FAIL; } - HRESULT addSectReloc(unsigned offset, PESection *relativeTo, - CeeSectionRelocType reloc, - CeeSectionRelocExtra *extra) { _ASSERTE(!"PESeedSection"); return E_FAIL; } - HRESULT addBaseReloc(unsigned offset, CeeSectionRelocType reloc, - CeeSectionRelocExtra *extra) { _ASSERTE(!"PESeedSection"); return E_FAIL; } -// unsigned char *name(); -// unsigned flags(); -// unsigned getBaseRVA(); - int getDirEntry() { _ASSERTE(!"PESeedSection"); return 0; } - HRESULT directoryEntry(unsigned num) { _ASSERTE(!"PESeedSection"); return E_FAIL; } - char * computePointer(unsigned offset) const { _ASSERTE(!"PESeedSection"); return NULL; } - BOOL containsPointer(_In_ char *ptr) const { _ASSERTE(!"PESeedSection"); return FALSE; } - unsigned computeOffset(_In_ char *ptr) const { _ASSERTE(!"PESeedSection"); return 0; } - HRESULT cloneInstance(PESection *destination) { _ASSERTE(!"PESeedSection"); return E_FAIL; } - - // PEWriterSection - - HRESULT applyRelocs(IMAGE_NT_HEADERS * pNtHeaders, - PERelocSection * relocSection, - CeeGenTokenMapper * pTokenMapper, - DWORD rdataRvaBase, - DWORD dataRvaBase, - DWORD textRvaBase) { return S_OK; } - - HRESULT write(HANDLE file); - unsigned writeMem(void ** pMem); - bool isSeedSection() { return true; } - -protected: - - PEDecoder * m_pSeedFileDecoder; - IMAGE_SECTION_HEADER * m_pSeedSectionHeader; - }; inline DWORD PEWriter::getSectionAlignment() { - return VAL32(m_ntHeaders->OptionalHeader.FileAlignment); + return VAL32(m_ntHeaders->OptionalHeader.SectionAlignment); } inline void PEWriter::setSectionAlignment(DWORD SectionAlignment) { - - _ASSERTE(m_hSeedFile == INVALID_HANDLE_VALUE); m_ntHeaders->OptionalHeader.SectionAlignment = VAL32(SectionAlignment); } @@ -296,7 +222,6 @@ inline DWORD PEWriter::getFileAlignment() { } inline void PEWriter::setFileAlignment(DWORD fileAlignment) { - _ASSERTE(m_hSeedFile == INVALID_HANDLE_VALUE); m_ntHeaders->OptionalHeader.FileAlignment = VAL32(fileAlignment); } diff --git a/src/coreclr/gc/gc.cpp b/src/coreclr/gc/gc.cpp index 5409d99a5380d9..453cff7b31e921 100644 --- a/src/coreclr/gc/gc.cpp +++ b/src/coreclr/gc/gc.cpp @@ -7841,7 +7841,7 @@ void gc_heap::fix_allocation_context_heaps (gc_alloc_context* gc_context, void*) // make sure no allocation contexts point to idle heaps void gc_heap::fix_allocation_contexts_heaps() { - GCToEEInterface::GcEnumAllocContexts (fix_allocation_context_heaps, nullptr); + GCToEEInterface::GcEnumAllocContexts (fix_allocation_context_heaps, nullptr); } #endif //MULTIPLE_HEAPS @@ -10596,7 +10596,7 @@ static int __cdecl cmp_mark_list_item (const void* vkey, const void* vdatum) #endif // _DEBUG #ifdef USE_REGIONS -uint8_t** gc_heap::get_region_mark_list (uint8_t* start, uint8_t* end, uint8_t*** mark_list_end_ptr) +uint8_t** gc_heap::get_region_mark_list (BOOL& use_mark_list, uint8_t* start, uint8_t* end, uint8_t*** mark_list_end_ptr) { size_t region_number = get_basic_region_index_for_address (start); size_t source_number = region_number; @@ -10726,6 +10726,13 @@ void gc_heap::merge_mark_lists (size_t total_mark_list_size) // blast this piece to the mark list append_to_mark_list(source[lowest_source], x); +#ifdef USE_REGIONS + if (mark_list_index > mark_list_end) + { + use_mark_list = false; + return nullptr; + } +#endif //USE_REGIONS piece_count++; source[lowest_source] = x; @@ -10745,6 +10752,13 @@ void gc_heap::merge_mark_lists (size_t total_mark_list_size) } // we're left with just one source that we copy append_to_mark_list(source[0], source_end[0]); +#ifdef USE_REGIONS + if (mark_list_index > mark_list_end) + { + use_mark_list = false; + return nullptr; + } +#endif //USE_REGIONS piece_count++; } @@ -10801,7 +10815,7 @@ static uint8_t** binary_search (uint8_t** left, uint8_t** right, uint8_t* e) return a + l; } -uint8_t** gc_heap::get_region_mark_list (uint8_t* start, uint8_t* end, uint8_t*** mark_list_end_ptr) +uint8_t** gc_heap::get_region_mark_list (BOOL& use_mark_list, uint8_t* start, uint8_t* end, uint8_t*** mark_list_end_ptr) { // do a binary search over the sorted marked list to find start and end of the // mark list for this region @@ -14170,7 +14184,7 @@ gc_heap::init_semi_shared() #ifdef MULTIPLE_HEAPS mark_list_size = min (100*1024, max (8192, soh_segment_size/(2*10*32))); #ifdef DYNAMIC_HEAP_COUNT - if (GCConfig::GetGCDynamicAdaptation() && GCConfig::GetHeapCount() == 0) + if (GCConfig::GetGCDynamicAdaptationMode() == 1 && GCConfig::GetHeapCount() == 0) { // we'll actually start with one heap in this case g_mark_list_total_size = mark_list_size; @@ -14380,7 +14394,7 @@ gc_heap::init_semi_shared() #endif //FEATURE_EVENT_TRACE conserve_mem_setting = (int)GCConfig::GetGCConserveMem(); - if (conserve_mem_setting == 0 && GCConfig::GetGCDynamicAdaptation()) + if (conserve_mem_setting == 0 && GCConfig::GetGCDynamicAdaptationMode() == 1) conserve_mem_setting = 5; if (conserve_mem_setting < 0) conserve_mem_setting = 0; @@ -15837,9 +15851,9 @@ void allocator::count_items (gc_heap* this_hp, size_t* fl_items_count, size_t* f assert (((CObjectHeader*)free_item)->IsFree()); num_fl_items++; - // Get the heap its region belongs to see if we need to put it back. + // Get the heap its region belongs to see if we need to put it back. heap_segment* region = gc_heap::region_of (free_item); - dprintf (3, ("b#%2d FL %Ix region %Ix heap %d -> %d", + dprintf (3, ("b#%2d FL %Ix region %Ix heap %d -> %d", i, free_item, (size_t)region, this_hp->heap_number, region->heap->heap_number)); if (region->heap != this_hp) { @@ -15848,7 +15862,7 @@ void allocator::count_items (gc_heap* this_hp, size_t* fl_items_count, size_t* f //if ((num_fl_items_rethread % 1000) == 0) //{ // end_us = GetHighPrecisionTimeStamp(); - // dprintf (8888, ("%Id items rethreaded out of %Id items in %I64d us, current fl: %Ix", + // dprintf (8888, ("%Id items rethreaded out of %Id items in %I64d us, current fl: %Ix", // num_fl_items_rethread, num_fl_items, (end_us - start_us), free_item)); // start_us = end_us; //} @@ -15940,9 +15954,9 @@ void allocator::rethread_items (size_t* num_total_fl_items, size_t* num_total_fl assert (((CObjectHeader*)free_item)->IsFree()); num_fl_items++; - // Get the heap its region belongs to see if we need to put it back. + // Get the heap its region belongs to see if we need to put it back. heap_segment* region = gc_heap::region_of (free_item); - dprintf (3, ("b#%2d FL %Ix region %Ix heap %d -> %d", + dprintf (3, ("b#%2d FL %Ix region %Ix heap %d -> %d", i, free_item, (size_t)region, current_heap->heap_number, region->heap->heap_number)); // need to keep track of heap and only check if it's not from our heap!! if (region->heap != current_heap) @@ -15986,7 +16000,7 @@ void allocator::rethread_items (size_t* num_total_fl_items, size_t* num_total_fl // merge buckets from min_fl_list to their corresponding buckets to this FL. void allocator::merge_items (gc_heap* current_heap, int to_num_heaps, int from_num_heaps) { - int this_hn = current_heap->heap_number; + int this_hn = current_heap->heap_number; for (unsigned int i = 0; i < num_buckets; i++) { @@ -22481,7 +22495,7 @@ void gc_heap::gc1() bool gc_heap::prepare_rethread_fl_items() { if (!min_fl_list) - { + { min_fl_list = new (nothrow) min_fl_list_info [MAX_BUCKET_COUNT * n_max_heaps]; if (min_fl_list == nullptr) return false; @@ -24882,10 +24896,10 @@ void gc_heap::check_heap_count () return; } - if (!GCConfig::GetGCDynamicAdaptation()) + if (GCConfig::GetGCDynamicAdaptationMode() == 0) { // don't change the heap count dynamically if the feature isn't explicitly enabled - return; + return; } if (heap_number == 0) @@ -25875,8 +25889,8 @@ BOOL gc_heap::background_mark (uint8_t* o, uint8_t* low, uint8_t* high) { \ for (ptrdiff_t __i = 0; __i > cnt; __i--) \ { \ - HALF_SIZE_T skip = cur->val_serie[__i].skip; \ - HALF_SIZE_T nptrs = cur->val_serie[__i].nptrs; \ + HALF_SIZE_T skip = (cur->val_serie + __i)->skip; \ + HALF_SIZE_T nptrs = (cur->val_serie + __i)->nptrs; \ uint8_t** ppstop = parm + nptrs; \ if (!start_useful || (uint8_t*)ppstop > (start)) \ { \ @@ -30947,21 +30961,21 @@ void gc_heap::process_remaining_regions (int current_plan_gen_num, generation* c // // + if the pinned surv of a region is >= demotion_pinned_ratio_th (this will be dynamically tuned based on memory load), // it will be promoted to its normal planned generation unconditionally. - // + // // + if the pinned surv is < demotion_pinned_ratio_th, we will always demote it to gen0. We will record how many regions // have no survival at all - those will be empty and can be used to plan any non gen0 generation if needed. - // + // // Note! We could actually promote a region with non zero pinned survivors to whichever generation we'd like (eg, we could // promote a gen0 region to gen2). However it means we'd need to set cards on those objects because we will not have a chance // later. The benefit of doing this is small in general as when we get into this method, it's very rare we don't already // have planned regions in higher generations. So I don't think it's worth the complexicity for now. We may consider it // for the future. - // + // // + if after we are done walking the remaining regions, we still haven't successfully planned all the needed generations, // we check to see if we have enough in the regions that will be empty (note that we call set_region_plan_gen_num on // these regions which means they are planned in gen0. So we need to make sure at least gen0 has 1 region). If so // thread_final_regions will naturally get one from there so we don't need to call set_region_plan_gen_num to replace the - // plan gen num. + // plan gen num. // // + if we don't have enough in regions that will be empty, we'll need to ask for new regions and if we can't, we fall back // to the special sweep mode. @@ -31012,7 +31026,7 @@ void gc_heap::process_remaining_regions (int current_plan_gen_num, generation* c heap_segment_plan_allocated (nseg) = generation_allocation_pointer (consing_gen); decide_on_demotion_pin_surv (nseg, &to_be_empty_regions); - + heap_segment* next_seg = heap_segment_next_non_sip (nseg); if ((next_seg == 0) && (heap_segment_gen_num (nseg) > 0)) @@ -31610,7 +31624,7 @@ void gc_heap::plan_phase (int condemned_gen_number) uint8_t** mark_list_index = nullptr; uint8_t** mark_list_next = nullptr; if (use_mark_list) - mark_list_next = get_region_mark_list (x, end, &mark_list_index); + mark_list_next = get_region_mark_list (use_mark_list, x, end, &mark_list_index); #else // USE_REGIONS assert (!marked (x)); uint8_t** mark_list_next = &mark_list[0]; @@ -31898,7 +31912,7 @@ void gc_heap::plan_phase (int condemned_gen_number) current_brick = brick_of (x); #ifdef USE_REGIONS if (use_mark_list) - mark_list_next = get_region_mark_list (x, end, &mark_list_index); + mark_list_next = get_region_mark_list (use_mark_list, x, end, &mark_list_index); if (should_sweep_in_plan (seg1)) { @@ -31968,7 +31982,7 @@ void gc_heap::plan_phase (int condemned_gen_number) current_brick = brick_of (x); if (use_mark_list) - mark_list_next = get_region_mark_list (x, end, &mark_list_index); + mark_list_next = get_region_mark_list (use_mark_list, x, end, &mark_list_index); if (should_sweep_in_plan (seg1)) { @@ -46217,7 +46231,7 @@ void gc_heap::descr_generations (const char* msg) dprintf (1, ("[%5s] GC#%5Id total heap size: %Idmb (F: %Idmb %d%%) commit size: %Idmb, %0.3f min, %d,%d new in plan, %d in threading\n", msg, idx, alloc_size, frag_size, (int)((double)frag_size * 100.0 / (double)alloc_size), - commit_size, + commit_size, (double)elapsed_time_so_far / (double)1000000 / (double)60, total_new_gen0_regions_in_plns, total_new_regions_in_prr, total_new_regions_in_threading)); } @@ -48067,7 +48081,7 @@ HRESULT GCHeap::Initialize() { #ifdef DYNAMIC_HEAP_COUNT // if no heap count was specified, and we are told to adjust heap count dynamically ... - if (GCConfig::GetHeapCount() == 0 && GCConfig::GetGCDynamicAdaptation()) + if (GCConfig::GetHeapCount() == 0 && GCConfig::GetGCDynamicAdaptationMode() == 1) { // ... start with only 1 heap gc_heap::g_heaps[0]->change_heap_count (1); @@ -50509,7 +50523,7 @@ size_t gc_heap::get_gen0_min_size() int n_heaps = 1; #endif //SERVER_GC - if (GCConfig::GetGCConserveMem() != 0 || GCConfig::GetGCDynamicAdaptation()) + if (GCConfig::GetGCConserveMem() != 0 || GCConfig::GetGCDynamicAdaptationMode() == 1) { // if we are asked to be stingy with memory, limit gen 0 size gen0size = min (gen0size, (4*1024*1024)); diff --git a/src/coreclr/gc/gcconfig.h b/src/coreclr/gc/gcconfig.h index e5a551baa37d5e..72786778d5a978 100644 --- a/src/coreclr/gc/gcconfig.h +++ b/src/coreclr/gc/gcconfig.h @@ -138,7 +138,7 @@ class GCConfigStringHolder 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.") \ INT_CONFIG (GCSpinCountUnit, "GCSpinCountUnit", 0, 0, "Specifies the spin count unit used by the GC.") \ - BOOL_CONFIG (GCDynamicAdaptation, "GCDynamicAdaptation", NULL, false, "Enables varying the heap count dynamically in Server GC.") + INT_CONFIG (GCDynamicAdaptationMode, "GCDynamicAdaptationMode", "System.GC.DynamicAdaptationMode", 0, "Enable the GC to dynamically adapt to application sizes.") // This class is responsible for retreiving configuration information // for how the GC should operate. class GCConfig diff --git a/src/coreclr/gc/gcdesc.h b/src/coreclr/gc/gcdesc.h index 14cee1db9a4cc1..54a13dfdb8cdff 100644 --- a/src/coreclr/gc/gcdesc.h +++ b/src/coreclr/gc/gcdesc.h @@ -216,7 +216,7 @@ class CGCDesc /* Handle the repeating case - array of valuetypes */ for (ptrdiff_t __i = 0; __i > cnt; __i--) { - NumOfPointers += cur->val_serie[__i].nptrs; + NumOfPointers += (cur->val_serie + __i)->nptrs; } NumOfPointers *= NumComponents; diff --git a/src/coreclr/gc/gcpriv.h b/src/coreclr/gc/gcpriv.h index 14256523e02a0c..1263610d4bf456 100644 --- a/src/coreclr/gc/gcpriv.h +++ b/src/coreclr/gc/gcpriv.h @@ -3160,7 +3160,7 @@ class gc_heap PER_HEAP_ISOLATED_METHOD void grow_mark_list(); #ifdef USE_REGIONS - PER_HEAP_METHOD uint8_t** get_region_mark_list (uint8_t* start, uint8_t* end, uint8_t*** mark_list_end); + PER_HEAP_METHOD uint8_t** get_region_mark_list (BOOL& use_mark_list, uint8_t* start, uint8_t* end, uint8_t*** mark_list_end); #endif //USE_REGIONS #ifdef BACKGROUND_GC diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp index 83f3774936d6b5..4e506b95c9746b 100644 --- a/src/coreclr/hosts/corerun/corerun.cpp +++ b/src/coreclr/hosts/corerun/corerun.cpp @@ -247,7 +247,9 @@ static int run(const configuration& config) // Check if debugger attach scenario was requested. if (config.wait_to_debug) wait_for_debugger(); - + + config.dotenv_configuration.load_into_current_process(); + string_t exe_path = pal::get_exe_path(); // Determine the managed application's path. @@ -303,8 +305,6 @@ static int run(const configuration& config) } } - config.dotenv_configuration.load_into_current_process(); - actions.before_coreclr_load(); // Attempt to load CoreCLR. diff --git a/src/coreclr/inc/ceefilegenwriter.h b/src/coreclr/inc/ceefilegenwriter.h index 06e20a6bd1fbd8..0364767cd5f471 100644 --- a/src/coreclr/inc/ceefilegenwriter.h +++ b/src/coreclr/inc/ceefilegenwriter.h @@ -69,11 +69,8 @@ class CeeFileGenWriter : public CCeeGen HRESULT allocateIAT(); public: // Create with one of these two methods, not operator new - static HRESULT CreateNewInstance(CCeeGen *pCeeFileGenFrom, CeeFileGenWriter* & pGenWriter, - DWORD createFlags = ICEE_CREATE_FILE_PURE_IL); - // See ICeeFileGen.h for the definition of the bits used in createFlags - static HRESULT CreateNewInstanceEx(CCeeGen *pCeeFileGenFrom, CeeFileGenWriter* & pGenWriter, - DWORD createFlags, LPCWSTR seedFileName = NULL); + static HRESULT CreateNewInstance(CeeFileGenWriter* & pGenWriter, + DWORD createFlags = ICEE_CREATE_FILE_PURE_IL); virtual HRESULT Cleanup(); diff --git a/src/coreclr/inc/ceegen.h b/src/coreclr/inc/ceegen.h index cb86a18c3f8277..67cb10d646b1ac 100644 --- a/src/coreclr/inc/ceegen.h +++ b/src/coreclr/inc/ceegen.h @@ -185,7 +185,6 @@ class CCeeGen : public ICeeGenInternal { CeeGenTokenMapper *m_pTokenMap; BOOLEAN m_fTokenMapSupported; // temporary to support both models - IMapToken *m_pRemapHandler; CeeSection **m_sections; short m_numSections; @@ -238,9 +237,6 @@ class CCeeGen : public ICeeGenInternal { ULONG RVA, UCHAR **lpBuffer); - STDMETHODIMP GetIMapTokenIface ( - IUnknown **pIMapToken); - STDMETHODIMP GenerateCeeFile (); STDMETHODIMP GetIlSection ( @@ -276,8 +272,6 @@ class CCeeGen : public ICeeGenInternal { UCHAR **lpBuffer); // [OUT] Returned buffer - STDMETHODIMP AddNotificationHandler(IUnknown *pHandler); - // Write the metadata in "emitter" to the default metadata section is "section" is 0 // If 'section != 0, it will put the data in 'buffer'. This // buffer is assumed to be in 'section' at 'offset' and of size 'buffLen' @@ -307,14 +301,6 @@ class CCeeGen : public ICeeGenInternal { LIMITED_METHOD_CONTRACT; return m_pTokenMap; } - - virtual HRESULT addNotificationHandler(IUnknown *pHandler); - - //Clone is actually a misnomer here. This method will copy all of the - //instance variables and then do a deep copy (as necessary) of the sections. - //Section data will be appended onto any information already in the section. - //This is done to support the DynamicIL -> PersistedIL transform. - virtual HRESULT cloneInstance(CCeeGen *destination); }; // ***** CeeSection inline methods diff --git a/src/coreclr/inc/ceegentokenmapper.h b/src/coreclr/inc/ceegentokenmapper.h index a1bb9b7ef4e4cc..02d98c92d53c3b 100644 --- a/src/coreclr/inc/ceegentokenmapper.h +++ b/src/coreclr/inc/ceegentokenmapper.h @@ -48,7 +48,7 @@ friend class PESectionMan; static int IndexForType(mdToken tk); - CeeGenTokenMapper() : m_pIImport(0), m_cRefs(1), m_pIMapToken(NULL) { LIMITED_METHOD_CONTRACT; } + CeeGenTokenMapper() : m_pIImport(0), m_cRefs(1) { LIMITED_METHOD_CONTRACT; } virtual ~CeeGenTokenMapper() {} //***************************************************************************** @@ -66,12 +66,6 @@ friend class PESectionMan; ULONG cRefs = --m_cRefs; if (cRefs == 0) { - if (m_pIMapToken) - { - m_pIMapToken->Release(); - m_pIMapToken = NULL; - } - delete this; } return cRefs; @@ -104,28 +98,6 @@ friend class PESectionMan; //***************************************************************************** virtual HRESULT GetMetaData(IMetaDataImport **ppIImport); -//***************************************************************************** -// Add another token mapper. -//***************************************************************************** - virtual HRESULT AddTokenMapper(IMapToken *pIMapToken) - { - STATIC_CONTRACT_NOTHROW; - STATIC_CONTRACT_FORBID_FAULT; - - // Add the token mapper, if there isn't already one. - if (m_pIMapToken == NULL) - { - m_pIMapToken = pIMapToken; - m_pIMapToken->AddRef(); - return S_OK; - } - else - { - _ASSERTE(!"Token mapper already set!"); - return E_FAIL; - } - } - protected: // m_rgMap is an array indexed by token type. For each type, an array of // tokens is kept, indexed by from rid. To see if a token has been moved, @@ -134,8 +106,6 @@ friend class PESectionMan; TOKENMAP m_rgMap[MAX_TOKENMAP]; IMetaDataImport *m_pIImport; ULONG m_cRefs; // Ref count. - IMapToken *m_pIMapToken; - }; #endif // __CeeGenTokenMapper_h__ diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h index 184b8f6b759c61..824be81ec313be 100644 --- a/src/coreclr/inc/clrconfigvalues.h +++ b/src/coreclr/inc/clrconfigvalues.h @@ -320,17 +320,6 @@ RETAIL_CONFIG_STRING_INFO(EXTERNAL_AltJitOs, W("AltJitOS"), "Sets target OS for RETAIL_CONFIG_STRING_INFO(EXTERNAL_AltJitExcludeAssemblies, W("AltJitExcludeAssemblies"), "Do not use AltJit on this semicolon-delimited list of assemblies.") #endif // defined(ALLOW_SXS_JIT) -#if defined(FEATURE_STACK_SAMPLING) -RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_StackSamplingEnabled, W("StackSamplingEnabled"), 0, "Is stack sampling based tracking of evolving hot methods enabled.") -RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_StackSamplingAfter, W("StackSamplingAfter"), 0, "When to start sampling (for some sort of app steady state), i.e., initial delay for sampling start in milliseconds.") -RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_StackSamplingEvery, W("StackSamplingEvery"), 100, "How frequent should thread stacks be sampled in milliseconds.") -RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_StackSamplingNumMethods, W("StackSamplingNumMethods"), 32, "Number of evolving methods to track as hot and JIT them in the background at a given point of execution.") -#endif // defined(FEATURE_JIT_SAMPLING) - -#if defined(ALLOW_SXS_JIT_NGEN) -RETAIL_CONFIG_STRING_INFO(INTERNAL_AltJitNgen, W("AltJitNgen"), "Enables AltJit for NGEN and selectively limits it to the specified methods.") -#endif // defined(ALLOW_SXS_JIT_NGEN) - RETAIL_CONFIG_DWORD_INFO(EXTERNAL_JitHostMaxSlabCache, W("JitHostMaxSlabCache"), 0x1000000, "Sets jit host max slab cache size, 16MB default") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_JitOptimizeType, W("JitOptimizeType"), 0 /* OPT_DEFAULT */, "") @@ -357,12 +346,6 @@ RETAIL_CONFIG_DWORD_INFO(EXTERNAL_JitRegisterFP, W("JitRegisterFP"), 3, "Control RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitELTHookEnabled, W("JitELTHookEnabled"), 0, "On ARM, setting this will emit Enter/Leave/TailCall callbacks") RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitMemStats, W("JitMemStats"), 0, "Display JIT memory usage statistics") RETAIL_CONFIG_DWORD_INFO(INTERNAL_JitVNMapSelBudget, W("JitVNMapSelBudget"), 100, "Max # of MapSelect's considered for a particular top-level invocation.") -#if defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_ARM64) -#define EXTERNAL_FeatureSIMD_Default 1 -#else // !(defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_ARM64)) -#define EXTERNAL_FeatureSIMD_Default 0 -#endif // !(defined(TARGET_AMD64) || defined(TARGET_X86) || defined(TARGET_ARM64)) -RETAIL_CONFIG_DWORD_INFO(INTERNAL_SIMD16ByteOnly, W("SIMD16ByteOnly"), 0, "Limit maximum SIMD vector length to 16 bytes (used by x64_arm64_altjit)") RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TrackDynamicMethodDebugInfo, W("TrackDynamicMethodDebugInfo"), 0, "Specifies whether debug info should be generated and tracked for dynamic methods") #ifdef FEATURE_MULTICOREJIT @@ -577,11 +560,11 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_HillClimbing_GainExponent, #endif // _DEBUG RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TieredCompilation, W("TieredCompilation"), 1, "Enables tiered compilation") RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TC_QuickJit, W("TC_QuickJit"), 1, "For methods that would be jitted, enable using quick JIT when appropriate.") -#if defined(TARGET_AMD64) || defined(TARGET_ARM64) +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TC_QuickJitForLoops, W("TC_QuickJitForLoops"), 1, "When quick JIT is enabled, quick JIT may also be used for methods that contain loops.") -#else // !(defined(TARGET_AMD64) || defined(TARGET_ARM64)) +#else // !(defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64)) RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_TC_QuickJitForLoops, W("TC_QuickJitForLoops"), 0, "When quick JIT is enabled, quick JIT may also be used for methods that contain loops.") -#endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) +#endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) RETAIL_CONFIG_DWORD_INFO(EXTERNAL_TC_AggressiveTiering, W("TC_AggressiveTiering"), 0, "Transition through tiers aggressively.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_BackgroundWorkerTimeoutMs, W("TC_BackgroundWorkerTimeoutMs"), TC_BackgroundWorkerTimeoutMs, "How long in milliseconds the background worker thread may remain idle before exiting.") RETAIL_CONFIG_DWORD_INFO(INTERNAL_TC_CallCountThreshold, W("TC_CallCountThreshold"), TC_CallCountThreshold, "Number of times a method must be called in tier 0 after which it is promoted to the next tier.") @@ -745,15 +728,17 @@ RETAIL_CONFIG_DWORD_INFO(INTERNAL_GDBJitEmitDebugFrame, W("GDBJitEmitDebugFrame" #endif #endif +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_MaxVectorTBitWidth, W("MaxVectorTBitWidth"), 0, "The maximum width, in bits, that Vector is allowed to be. A value less than 128 is treated as the system default.") + // // Hardware Intrinsic ISAs; keep in sync with jitconfigvalues.h // #if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) //TODO: should implement LoongArch64's features. //TODO-RISCV64-CQ: should implement RISCV64's features. -RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableHWIntrinsic, W("EnableHWIntrinsic"), 0, "Allows Base+ hardware intrinsics to be disabled") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableHWIntrinsic, W("EnableHWIntrinsic"), 0, "Allows Base+ hardware intrinsics to be disabled") #else -RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableHWIntrinsic, W("EnableHWIntrinsic"), 1, "Allows Base+ hardware intrinsics to be disabled") +RETAIL_CONFIG_DWORD_INFO(EXTERNAL_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) diff --git a/src/coreclr/inc/corerror.xml b/src/coreclr/inc/corerror.xml index afeaf4f602a4ad..81c7bab5ea1f0a 100644 --- a/src/coreclr/inc/corerror.xml +++ b/src/coreclr/inc/corerror.xml @@ -1603,7 +1603,7 @@ COR_E_TARGET "Attempt to invoke non-static method with a null Object." - - If you attempt to invoke a non-static method with a null Object - If you atte + If you attempt to invoke a non-static method with a null Object diff --git a/src/coreclr/inc/corinfoinstructionset.h b/src/coreclr/inc/corinfoinstructionset.h index 8462ab33413ef9..5aecf46bf3928c 100644 --- a/src/coreclr/inc/corinfoinstructionset.h +++ b/src/coreclr/inc/corinfoinstructionset.h @@ -14,7 +14,7 @@ enum CORINFO_InstructionSet { InstructionSet_ILLEGAL = 0, - InstructionSet_NONE = 63, + InstructionSet_NONE = 127, #ifdef TARGET_ARM64 InstructionSet_ArmBase=1, InstructionSet_AdvSimd=2, @@ -29,14 +29,15 @@ enum CORINFO_InstructionSet InstructionSet_Vector128=11, InstructionSet_Dczva=12, InstructionSet_Rcpc=13, - InstructionSet_ArmBase_Arm64=14, - InstructionSet_AdvSimd_Arm64=15, - InstructionSet_Aes_Arm64=16, - InstructionSet_Crc32_Arm64=17, - InstructionSet_Dp_Arm64=18, - InstructionSet_Rdm_Arm64=19, - InstructionSet_Sha1_Arm64=20, - InstructionSet_Sha256_Arm64=21, + InstructionSet_VectorT128=14, + InstructionSet_ArmBase_Arm64=15, + InstructionSet_AdvSimd_Arm64=16, + InstructionSet_Aes_Arm64=17, + InstructionSet_Crc32_Arm64=18, + InstructionSet_Dp_Arm64=19, + InstructionSet_Rdm_Arm64=20, + InstructionSet_Sha1_Arm64=21, + InstructionSet_Sha256_Arm64=22, #endif // TARGET_ARM64 #ifdef TARGET_AMD64 InstructionSet_X86Base=1, @@ -71,35 +72,38 @@ enum CORINFO_InstructionSet InstructionSet_AVX512DQ_VL=30, InstructionSet_AVX512VBMI=31, InstructionSet_AVX512VBMI_VL=32, - InstructionSet_X86Base_X64=33, - InstructionSet_SSE_X64=34, - InstructionSet_SSE2_X64=35, - InstructionSet_SSE3_X64=36, - InstructionSet_SSSE3_X64=37, - InstructionSet_SSE41_X64=38, - InstructionSet_SSE42_X64=39, - InstructionSet_AVX_X64=40, - InstructionSet_AVX2_X64=41, - InstructionSet_AES_X64=42, - InstructionSet_BMI1_X64=43, - InstructionSet_BMI2_X64=44, - InstructionSet_FMA_X64=45, - InstructionSet_LZCNT_X64=46, - InstructionSet_PCLMULQDQ_X64=47, - InstructionSet_POPCNT_X64=48, - InstructionSet_AVXVNNI_X64=49, - InstructionSet_MOVBE_X64=50, - InstructionSet_X86Serialize_X64=51, - InstructionSet_AVX512F_X64=52, - InstructionSet_AVX512F_VL_X64=53, - InstructionSet_AVX512BW_X64=54, - InstructionSet_AVX512BW_VL_X64=55, - InstructionSet_AVX512CD_X64=56, - InstructionSet_AVX512CD_VL_X64=57, - InstructionSet_AVX512DQ_X64=58, - InstructionSet_AVX512DQ_VL_X64=59, - InstructionSet_AVX512VBMI_X64=60, - InstructionSet_AVX512VBMI_VL_X64=61, + InstructionSet_VectorT128=33, + InstructionSet_VectorT256=34, + InstructionSet_VectorT512=35, + InstructionSet_X86Base_X64=36, + InstructionSet_SSE_X64=37, + InstructionSet_SSE2_X64=38, + InstructionSet_SSE3_X64=39, + InstructionSet_SSSE3_X64=40, + InstructionSet_SSE41_X64=41, + InstructionSet_SSE42_X64=42, + InstructionSet_AVX_X64=43, + InstructionSet_AVX2_X64=44, + InstructionSet_AES_X64=45, + InstructionSet_BMI1_X64=46, + InstructionSet_BMI2_X64=47, + InstructionSet_FMA_X64=48, + InstructionSet_LZCNT_X64=49, + InstructionSet_PCLMULQDQ_X64=50, + InstructionSet_POPCNT_X64=51, + InstructionSet_AVXVNNI_X64=52, + InstructionSet_MOVBE_X64=53, + InstructionSet_X86Serialize_X64=54, + InstructionSet_AVX512F_X64=55, + InstructionSet_AVX512F_VL_X64=56, + InstructionSet_AVX512BW_X64=57, + InstructionSet_AVX512BW_VL_X64=58, + InstructionSet_AVX512CD_X64=59, + InstructionSet_AVX512CD_VL_X64=60, + InstructionSet_AVX512DQ_X64=61, + InstructionSet_AVX512DQ_VL_X64=62, + InstructionSet_AVX512VBMI_X64=63, + InstructionSet_AVX512VBMI_VL_X64=64, #endif // TARGET_AMD64 #ifdef TARGET_X86 InstructionSet_X86Base=1, @@ -134,35 +138,38 @@ enum CORINFO_InstructionSet InstructionSet_AVX512DQ_VL=30, InstructionSet_AVX512VBMI=31, InstructionSet_AVX512VBMI_VL=32, - InstructionSet_X86Base_X64=33, - InstructionSet_SSE_X64=34, - InstructionSet_SSE2_X64=35, - InstructionSet_SSE3_X64=36, - InstructionSet_SSSE3_X64=37, - InstructionSet_SSE41_X64=38, - InstructionSet_SSE42_X64=39, - InstructionSet_AVX_X64=40, - InstructionSet_AVX2_X64=41, - InstructionSet_AES_X64=42, - InstructionSet_BMI1_X64=43, - InstructionSet_BMI2_X64=44, - InstructionSet_FMA_X64=45, - InstructionSet_LZCNT_X64=46, - InstructionSet_PCLMULQDQ_X64=47, - InstructionSet_POPCNT_X64=48, - InstructionSet_AVXVNNI_X64=49, - InstructionSet_MOVBE_X64=50, - InstructionSet_X86Serialize_X64=51, - InstructionSet_AVX512F_X64=52, - InstructionSet_AVX512F_VL_X64=53, - InstructionSet_AVX512BW_X64=54, - InstructionSet_AVX512BW_VL_X64=55, - InstructionSet_AVX512CD_X64=56, - InstructionSet_AVX512CD_VL_X64=57, - InstructionSet_AVX512DQ_X64=58, - InstructionSet_AVX512DQ_VL_X64=59, - InstructionSet_AVX512VBMI_X64=60, - InstructionSet_AVX512VBMI_VL_X64=61, + InstructionSet_VectorT128=33, + InstructionSet_VectorT256=34, + InstructionSet_VectorT512=35, + InstructionSet_X86Base_X64=36, + InstructionSet_SSE_X64=37, + InstructionSet_SSE2_X64=38, + InstructionSet_SSE3_X64=39, + InstructionSet_SSSE3_X64=40, + InstructionSet_SSE41_X64=41, + InstructionSet_SSE42_X64=42, + InstructionSet_AVX_X64=43, + InstructionSet_AVX2_X64=44, + InstructionSet_AES_X64=45, + InstructionSet_BMI1_X64=46, + InstructionSet_BMI2_X64=47, + InstructionSet_FMA_X64=48, + InstructionSet_LZCNT_X64=49, + InstructionSet_PCLMULQDQ_X64=50, + InstructionSet_POPCNT_X64=51, + InstructionSet_AVXVNNI_X64=52, + InstructionSet_MOVBE_X64=53, + InstructionSet_X86Serialize_X64=54, + InstructionSet_AVX512F_X64=55, + InstructionSet_AVX512F_VL_X64=56, + InstructionSet_AVX512BW_X64=57, + InstructionSet_AVX512BW_VL_X64=58, + InstructionSet_AVX512CD_X64=59, + InstructionSet_AVX512CD_VL_X64=60, + InstructionSet_AVX512DQ_X64=61, + InstructionSet_AVX512DQ_VL_X64=62, + InstructionSet_AVX512VBMI_X64=63, + InstructionSet_AVX512VBMI_VL_X64=64, #endif // TARGET_X86 }; @@ -170,7 +177,7 @@ enum CORINFO_InstructionSet struct CORINFO_InstructionSetFlags { private: - static const int32_t FlagsFieldCount = 1; + static const int32_t FlagsFieldCount = 2; static const int32_t BitsPerFlagsField = sizeof(uint64_t) * 8; uint64_t _flags[FlagsFieldCount] = { }; @@ -404,6 +411,8 @@ inline CORINFO_InstructionSetFlags EnsureInstructionSetFlagsAreValid(CORINFO_Ins resultflags.RemoveInstructionSet(InstructionSet_Vector64); if (resultflags.HasInstructionSet(InstructionSet_Vector128) && !resultflags.HasInstructionSet(InstructionSet_AdvSimd)) resultflags.RemoveInstructionSet(InstructionSet_Vector128); + if (resultflags.HasInstructionSet(InstructionSet_VectorT128) && !resultflags.HasInstructionSet(InstructionSet_AdvSimd)) + resultflags.RemoveInstructionSet(InstructionSet_VectorT128); #endif // TARGET_ARM64 #ifdef TARGET_AMD64 if (resultflags.HasInstructionSet(InstructionSet_X86Base) && !resultflags.HasInstructionSet(InstructionSet_X86Base_X64)) @@ -566,24 +575,46 @@ inline CORINFO_InstructionSetFlags EnsureInstructionSetFlagsAreValid(CORINFO_Ins resultflags.RemoveInstructionSet(InstructionSet_X86Serialize); if (resultflags.HasInstructionSet(InstructionSet_AVX512F) && !resultflags.HasInstructionSet(InstructionSet_AVX2)) resultflags.RemoveInstructionSet(InstructionSet_AVX512F); + if (resultflags.HasInstructionSet(InstructionSet_AVX512F) && !resultflags.HasInstructionSet(InstructionSet_FMA)) + resultflags.RemoveInstructionSet(InstructionSet_AVX512F); if (resultflags.HasInstructionSet(InstructionSet_AVX512F_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512F)) resultflags.RemoveInstructionSet(InstructionSet_AVX512F_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512CD) && !resultflags.HasInstructionSet(InstructionSet_AVX512F)) resultflags.RemoveInstructionSet(InstructionSet_AVX512CD); + if (resultflags.HasInstructionSet(InstructionSet_AVX512CD_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512CD)) + resultflags.RemoveInstructionSet(InstructionSet_AVX512CD_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512CD_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512F_VL)) resultflags.RemoveInstructionSet(InstructionSet_AVX512CD_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512BW) && !resultflags.HasInstructionSet(InstructionSet_AVX512F)) resultflags.RemoveInstructionSet(InstructionSet_AVX512BW); + if (resultflags.HasInstructionSet(InstructionSet_AVX512BW_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512BW)) + resultflags.RemoveInstructionSet(InstructionSet_AVX512BW_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512BW_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512F_VL)) resultflags.RemoveInstructionSet(InstructionSet_AVX512BW_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512DQ) && !resultflags.HasInstructionSet(InstructionSet_AVX512F)) resultflags.RemoveInstructionSet(InstructionSet_AVX512DQ); + if (resultflags.HasInstructionSet(InstructionSet_AVX512DQ_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512DQ)) + resultflags.RemoveInstructionSet(InstructionSet_AVX512DQ_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512DQ_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512F_VL)) resultflags.RemoveInstructionSet(InstructionSet_AVX512DQ_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512VBMI) && !resultflags.HasInstructionSet(InstructionSet_AVX512BW)) resultflags.RemoveInstructionSet(InstructionSet_AVX512VBMI); + if (resultflags.HasInstructionSet(InstructionSet_AVX512VBMI_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512VBMI)) + resultflags.RemoveInstructionSet(InstructionSet_AVX512VBMI_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512VBMI_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512BW_VL)) resultflags.RemoveInstructionSet(InstructionSet_AVX512VBMI_VL); + if (resultflags.HasInstructionSet(InstructionSet_VectorT128) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) + resultflags.RemoveInstructionSet(InstructionSet_VectorT128); + if (resultflags.HasInstructionSet(InstructionSet_VectorT256) && !resultflags.HasInstructionSet(InstructionSet_AVX2)) + resultflags.RemoveInstructionSet(InstructionSet_VectorT256); + if (resultflags.HasInstructionSet(InstructionSet_VectorT512) && !resultflags.HasInstructionSet(InstructionSet_AVX512F)) + resultflags.RemoveInstructionSet(InstructionSet_VectorT512); + if (resultflags.HasInstructionSet(InstructionSet_AVX512F) && !resultflags.HasInstructionSet(InstructionSet_AVX512BW_VL)) + resultflags.RemoveInstructionSet(InstructionSet_AVX512F); + if (resultflags.HasInstructionSet(InstructionSet_AVX512F) && !resultflags.HasInstructionSet(InstructionSet_AVX512CD_VL)) + resultflags.RemoveInstructionSet(InstructionSet_AVX512F); + if (resultflags.HasInstructionSet(InstructionSet_AVX512F) && !resultflags.HasInstructionSet(InstructionSet_AVX512DQ_VL)) + resultflags.RemoveInstructionSet(InstructionSet_AVX512F); #endif // TARGET_AMD64 #ifdef TARGET_X86 if (resultflags.HasInstructionSet(InstructionSet_SSE) && !resultflags.HasInstructionSet(InstructionSet_X86Base)) @@ -630,24 +661,46 @@ inline CORINFO_InstructionSetFlags EnsureInstructionSetFlagsAreValid(CORINFO_Ins resultflags.RemoveInstructionSet(InstructionSet_X86Serialize); if (resultflags.HasInstructionSet(InstructionSet_AVX512F) && !resultflags.HasInstructionSet(InstructionSet_AVX2)) resultflags.RemoveInstructionSet(InstructionSet_AVX512F); + if (resultflags.HasInstructionSet(InstructionSet_AVX512F) && !resultflags.HasInstructionSet(InstructionSet_FMA)) + resultflags.RemoveInstructionSet(InstructionSet_AVX512F); if (resultflags.HasInstructionSet(InstructionSet_AVX512F_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512F)) resultflags.RemoveInstructionSet(InstructionSet_AVX512F_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512CD) && !resultflags.HasInstructionSet(InstructionSet_AVX512F)) resultflags.RemoveInstructionSet(InstructionSet_AVX512CD); + if (resultflags.HasInstructionSet(InstructionSet_AVX512CD_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512CD)) + resultflags.RemoveInstructionSet(InstructionSet_AVX512CD_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512CD_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512F_VL)) resultflags.RemoveInstructionSet(InstructionSet_AVX512CD_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512BW) && !resultflags.HasInstructionSet(InstructionSet_AVX512F)) resultflags.RemoveInstructionSet(InstructionSet_AVX512BW); + if (resultflags.HasInstructionSet(InstructionSet_AVX512BW_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512BW)) + resultflags.RemoveInstructionSet(InstructionSet_AVX512BW_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512BW_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512F_VL)) resultflags.RemoveInstructionSet(InstructionSet_AVX512BW_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512DQ) && !resultflags.HasInstructionSet(InstructionSet_AVX512F)) resultflags.RemoveInstructionSet(InstructionSet_AVX512DQ); + if (resultflags.HasInstructionSet(InstructionSet_AVX512DQ_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512DQ)) + resultflags.RemoveInstructionSet(InstructionSet_AVX512DQ_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512DQ_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512F_VL)) resultflags.RemoveInstructionSet(InstructionSet_AVX512DQ_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512VBMI) && !resultflags.HasInstructionSet(InstructionSet_AVX512BW)) resultflags.RemoveInstructionSet(InstructionSet_AVX512VBMI); + if (resultflags.HasInstructionSet(InstructionSet_AVX512VBMI_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512VBMI)) + resultflags.RemoveInstructionSet(InstructionSet_AVX512VBMI_VL); if (resultflags.HasInstructionSet(InstructionSet_AVX512VBMI_VL) && !resultflags.HasInstructionSet(InstructionSet_AVX512BW_VL)) resultflags.RemoveInstructionSet(InstructionSet_AVX512VBMI_VL); + if (resultflags.HasInstructionSet(InstructionSet_VectorT128) && !resultflags.HasInstructionSet(InstructionSet_SSE2)) + resultflags.RemoveInstructionSet(InstructionSet_VectorT128); + if (resultflags.HasInstructionSet(InstructionSet_VectorT256) && !resultflags.HasInstructionSet(InstructionSet_AVX2)) + resultflags.RemoveInstructionSet(InstructionSet_VectorT256); + if (resultflags.HasInstructionSet(InstructionSet_VectorT512) && !resultflags.HasInstructionSet(InstructionSet_AVX512F)) + resultflags.RemoveInstructionSet(InstructionSet_VectorT512); + if (resultflags.HasInstructionSet(InstructionSet_AVX512F) && !resultflags.HasInstructionSet(InstructionSet_AVX512BW_VL)) + resultflags.RemoveInstructionSet(InstructionSet_AVX512F); + if (resultflags.HasInstructionSet(InstructionSet_AVX512F) && !resultflags.HasInstructionSet(InstructionSet_AVX512CD_VL)) + resultflags.RemoveInstructionSet(InstructionSet_AVX512F); + if (resultflags.HasInstructionSet(InstructionSet_AVX512F) && !resultflags.HasInstructionSet(InstructionSet_AVX512DQ_VL)) + resultflags.RemoveInstructionSet(InstructionSet_AVX512F); #endif // TARGET_X86 } while (!oldflags.Equals(resultflags)); @@ -706,6 +759,8 @@ inline const char *InstructionSetToString(CORINFO_InstructionSet instructionSet) return "Dczva"; case InstructionSet_Rcpc : return "Rcpc"; + case InstructionSet_VectorT128 : + return "VectorT128"; #endif // TARGET_ARM64 #ifdef TARGET_AMD64 case InstructionSet_X86Base : @@ -830,6 +885,12 @@ inline const char *InstructionSetToString(CORINFO_InstructionSet instructionSet) return "AVX512VBMI_VL"; case InstructionSet_AVX512VBMI_VL_X64 : return "AVX512VBMI_VL_X64"; + case InstructionSet_VectorT128 : + return "VectorT128"; + case InstructionSet_VectorT256 : + return "VectorT256"; + case InstructionSet_VectorT512 : + return "VectorT512"; #endif // TARGET_AMD64 #ifdef TARGET_X86 case InstructionSet_X86Base : @@ -896,6 +957,12 @@ inline const char *InstructionSetToString(CORINFO_InstructionSet instructionSet) return "AVX512VBMI"; case InstructionSet_AVX512VBMI_VL : return "AVX512VBMI_VL"; + case InstructionSet_VectorT128 : + return "VectorT128"; + case InstructionSet_VectorT256 : + return "VectorT256"; + case InstructionSet_VectorT512 : + return "VectorT512"; #endif // TARGET_X86 default: @@ -926,6 +993,7 @@ inline CORINFO_InstructionSet InstructionSetFromR2RInstructionSet(ReadyToRunInst case READYTORUN_INSTRUCTION_Sha256: return InstructionSet_Sha256; case READYTORUN_INSTRUCTION_Atomics: return InstructionSet_Atomics; case READYTORUN_INSTRUCTION_Rcpc: return InstructionSet_Rcpc; + case READYTORUN_INSTRUCTION_VectorT128: return InstructionSet_VectorT128; #endif // TARGET_ARM64 #ifdef TARGET_AMD64 case READYTORUN_INSTRUCTION_X86Base: return InstructionSet_X86Base; @@ -957,6 +1025,9 @@ inline CORINFO_InstructionSet InstructionSetFromR2RInstructionSet(ReadyToRunInst case READYTORUN_INSTRUCTION_Avx512DQ_VL: return InstructionSet_AVX512DQ_VL; case READYTORUN_INSTRUCTION_Avx512Vbmi: return InstructionSet_AVX512VBMI; case READYTORUN_INSTRUCTION_Avx512Vbmi_VL: return InstructionSet_AVX512VBMI_VL; + case READYTORUN_INSTRUCTION_VectorT128: return InstructionSet_VectorT128; + case READYTORUN_INSTRUCTION_VectorT256: return InstructionSet_VectorT256; + case READYTORUN_INSTRUCTION_VectorT512: return InstructionSet_VectorT512; #endif // TARGET_AMD64 #ifdef TARGET_X86 case READYTORUN_INSTRUCTION_X86Base: return InstructionSet_X86Base; @@ -988,6 +1059,9 @@ inline CORINFO_InstructionSet InstructionSetFromR2RInstructionSet(ReadyToRunInst case READYTORUN_INSTRUCTION_Avx512DQ_VL: return InstructionSet_AVX512DQ_VL; case READYTORUN_INSTRUCTION_Avx512Vbmi: return InstructionSet_AVX512VBMI; case READYTORUN_INSTRUCTION_Avx512Vbmi_VL: return InstructionSet_AVX512VBMI_VL; + case READYTORUN_INSTRUCTION_VectorT128: return InstructionSet_VectorT128; + case READYTORUN_INSTRUCTION_VectorT256: return InstructionSet_VectorT256; + case READYTORUN_INSTRUCTION_VectorT512: return InstructionSet_VectorT512; #endif // TARGET_X86 default: diff --git a/src/coreclr/inc/corjitflags.h b/src/coreclr/inc/corjitflags.h index cc4ad7900e2435..6f7b00cb6f9197 100644 --- a/src/coreclr/inc/corjitflags.h +++ b/src/coreclr/inc/corjitflags.h @@ -70,7 +70,7 @@ class CORJIT_FLAGS CORJIT_FLAG_BBINSTR_IF_LOOPS = 32, // JIT must instrument current method if it has loops CORJIT_FLAG_PUBLISH_SECRET_PARAM = 33, // JIT must place stub secret param into local 0. (used by IL stubs) CORJIT_FLAG_UNUSED14 = 34, - CORJIT_FLAG_SAMPLING_JIT_BACKGROUND = 35, // JIT is being invoked as a result of stack sampling for hot methods in the background + CORJIT_FLAG_UNUSED37 = 35, CORJIT_FLAG_USE_PINVOKE_HELPERS = 36, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions CORJIT_FLAG_REVERSE_PINVOKE = 37, // The JIT should insert REVERSE_PINVOKE_{ENTER,EXIT} helpers into method prolog/epilog CORJIT_FLAG_TRACK_TRANSITIONS = 38, // The JIT should insert the REVERSE_PINVOKE helper variants that track transitions. diff --git a/src/coreclr/inc/corpriv.h b/src/coreclr/inc/corpriv.h index 505ac83e1be984..9fa3fbb9f71d2c 100644 --- a/src/coreclr/inc/corpriv.h +++ b/src/coreclr/inc/corpriv.h @@ -403,9 +403,6 @@ DECLARE_INTERFACE_(ICeeGenInternal, IUnknown) ULONG RVA, // [IN] RVA for method to return UCHAR * *lpBuffer) PURE; // [OUT] Returned buffer - STDMETHOD(GetIMapTokenIface) ( - IUnknown * *pIMapToken) PURE; - STDMETHOD(GenerateCeeFile) () PURE; STDMETHOD(GetIlSection) ( diff --git a/src/coreclr/inc/iceefilegen.h b/src/coreclr/inc/iceefilegen.h index f0fb5b091c9cac..c3dc26f4d952fd 100644 --- a/src/coreclr/inc/iceefilegen.h +++ b/src/coreclr/inc/iceefilegen.h @@ -115,19 +115,12 @@ class ICeeFileGen { virtual HRESULT SetComImageFlags (HCEEFILE ceeFile, DWORD mask); virtual HRESULT GetComImageFlags (HCEEFILE ceeFile, DWORD *mask); - // get IMapToken interface for tracking mapped tokens - virtual HRESULT GetIMapTokenIface(HCEEFILE ceeFile, IMetaDataEmit *emitter, IUnknown **pIMapToken); virtual HRESULT SetDirectoryEntry (HCEEFILE ceeFile, HCEESECTION section, ULONG num, ULONG size, ULONG offset = 0); // Write out the metadata in "emitter" to the metadata section in "ceeFile" // Use EmitMetaDataAt() for more control virtual HRESULT EmitMetaDataEx (HCEEFILE ceeFile, IMetaDataEmit *emitter); - virtual HRESULT GetIMapTokenIfaceEx(HCEEFILE ceeFile, IMetaDataEmit *emitter, IUnknown **pIMapToken); - - virtual HRESULT CreateCeeFileFromICeeGen( - ICeeGenInternal *pFromICeeGen, HCEEFILE *ceeFile, DWORD createFlags = ICEE_CREATE_FILE_PURE_IL); // call this to instantiate a file handle - virtual HRESULT SetManifestEntry(HCEEFILE ceeFile, ULONG size, ULONG offset); virtual HRESULT ComputeSectionOffset(HCEESECTION section, _In_ char *ptr, @@ -164,12 +157,6 @@ class ICeeFileGen { virtual HRESULT GetFileTimeStamp (HCEEFILE ceeFile, DWORD *pTimeStamp); - // Add a notification handler. If it implements an interface that - // the ICeeFileGen understands, S_OK is returned. Otherwise, - // E_NOINTERFACE. - virtual HRESULT AddNotificationHandler(HCEEFILE ceeFile, - IUnknown *pHandler); - virtual HRESULT SetFileAlignment(HCEEFILE ceeFile, ULONG fileAlignment); virtual HRESULT ClearComImageFlags (HCEEFILE ceeFile, DWORD mask); @@ -182,13 +169,6 @@ class ICeeFileGen { PIMAGE_SECTION_HEADER *ppSections, ULONG *pNumSections); - // Seed file is a base file which is copied over into the output file - // Note that there are restrictions on the seed file (the sections - // cannot be relocated), and that the copy is not complete as the new - // headers overwrite the seed file headers. - virtual HRESULT CreateCeeFileEx2(HCEEFILE *ceeFile, ULONG createFlags, - LPCWSTR seedFileName = NULL); - virtual HRESULT SetVTableEntry64(HCEEFILE ceeFile, ULONG size, void* ptr); }; diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index eee46d6068395a..ebcf4919cb6afb 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 = { /* dfc41bc9-f134-4c50-897e-fc9304a82059 */ - 0xdfc41bc9, - 0xf134, - 0x4c50, - {0x89, 0x7e, 0xfc, 0x93, 0x04, 0xa8, 0x20, 0x59} +constexpr GUID JITEEVersionIdentifier = { /* fda2f9dd-6b3e-4ecd-a7b8-79e5edf1f072 */ + 0xfda2f9dd, + 0x6b3e, + 0x4ecd, + {0xa7, 0xb8, 0x79, 0xe5, 0xed, 0xf1, 0xf0, 0x72} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/inc/pedecoder.h b/src/coreclr/inc/pedecoder.h index 4ada5241163b7c..efd0555a4f7b9f 100644 --- a/src/coreclr/inc/pedecoder.h +++ b/src/coreclr/inc/pedecoder.h @@ -179,8 +179,6 @@ class PEDecoder DWORD GetCheckSum() const; WORD GetMachine() const; WORD GetCharacteristics() const; - DWORD GetFileAlignment() const; - DWORD GetSectionAlignment() const; SIZE_T GetSizeOfStackReserve() const; SIZE_T GetSizeOfStackCommit() const; SIZE_T GetSizeOfHeapReserve() const; diff --git a/src/coreclr/inc/pedecoder.inl b/src/coreclr/inc/pedecoder.inl index ea2440058f79d5..9b3c9c47238d15 100644 --- a/src/coreclr/inc/pedecoder.inl +++ b/src/coreclr/inc/pedecoder.inl @@ -383,36 +383,6 @@ inline DWORD PEDecoder::GetCheckSum() const return VAL32(FindNTHeaders()->OptionalHeader.CheckSum); } -inline DWORD PEDecoder::GetFileAlignment() const -{ - CONTRACTL - { - INSTANCE_CHECK; - PRECONDITION(CheckNTHeaders()); - NOTHROW; - GC_NOTRIGGER; - } - CONTRACTL_END; - - //even though some data in OptionalHeader is different for 32 and 64, this field is the same - return VAL32(FindNTHeaders()->OptionalHeader.FileAlignment); -} - -inline DWORD PEDecoder::GetSectionAlignment() const -{ - CONTRACTL - { - INSTANCE_CHECK; - PRECONDITION(CheckNTHeaders()); - NOTHROW; - GC_NOTRIGGER; - } - CONTRACTL_END; - - //even though some data in OptionalHeader is different for 32 and 64, this field is the same - return VAL32(FindNTHeaders()->OptionalHeader.SectionAlignment); -} - inline WORD PEDecoder::GetMachine() const { CONTRACTL diff --git a/src/coreclr/inc/pesectionman.h b/src/coreclr/inc/pesectionman.h index 042a5dfc26ce77..79e70c7dc916dd 100644 --- a/src/coreclr/inc/pesectionman.h +++ b/src/coreclr/inc/pesectionman.h @@ -38,8 +38,6 @@ class PESectionMan // Apply all the relocs for in memory conversion HRESULT applyRelocs(CeeGenTokenMapper *pTokenMapper); - HRESULT cloneInstance(PESectionMan *destination); - protected: // Finds section with given name. returns 0 if not found @@ -142,9 +140,6 @@ class PESection : public CeeSectionImpl { // computes an offset as if this were an array virtual unsigned computeOffset(_In_ char *ptr) const; - // Make 'destination' a copy of the current PESection - HRESULT cloneInstance(PESection *destination); - // Cause the section to allocate memory in smaller chunks void SetInitialGrowth(unsigned growth); diff --git a/src/coreclr/inc/readytoruninstructionset.h b/src/coreclr/inc/readytoruninstructionset.h index faf4a5028cc1c9..0a9a78e03f6c15 100644 --- a/src/coreclr/inc/readytoruninstructionset.h +++ b/src/coreclr/inc/readytoruninstructionset.h @@ -47,6 +47,9 @@ enum ReadyToRunInstructionSet READYTORUN_INSTRUCTION_Avx512DQ_VL=36, READYTORUN_INSTRUCTION_Avx512Vbmi=37, READYTORUN_INSTRUCTION_Avx512Vbmi_VL=38, + READYTORUN_INSTRUCTION_VectorT128=39, + READYTORUN_INSTRUCTION_VectorT256=40, + READYTORUN_INSTRUCTION_VectorT512=41, }; diff --git a/src/coreclr/inc/switches.h b/src/coreclr/inc/switches.h index 8b8ee515ef30b9..e19627fac1efad 100644 --- a/src/coreclr/inc/switches.h +++ b/src/coreclr/inc/switches.h @@ -74,10 +74,7 @@ #endif // ALLOW_SXS_JIT enables AltJit support for JIT-ing, via DOTNET_AltJit / DOTNET_AltJitName. -// ALLOW_SXS_JIT_NGEN enables AltJit support for NGEN, via DOTNET_AltJitNgen / DOTNET_AltJitName. -// Note that if ALLOW_SXS_JIT_NGEN is defined, then ALLOW_SXS_JIT must be defined. #define ALLOW_SXS_JIT -#define ALLOW_SXS_JIT_NGEN #if !defined(TARGET_UNIX) // PLATFORM_SUPPORTS_THREADSUSPEND is defined for platforms where it is safe to call @@ -168,9 +165,3 @@ #endif #define FEATURE_MINIMETADATA_IN_TRIAGEDUMPS - -// If defined, support interpretation. - -#if !defined(TARGET_UNIX) -#define FEATURE_STACK_SAMPLING -#endif // defined (ALLOW_SXS_JIT) diff --git a/src/coreclr/jit/block.cpp b/src/coreclr/jit/block.cpp index 7c57df63822c7c..5284e747092bd1 100644 --- a/src/coreclr/jit/block.cpp +++ b/src/coreclr/jit/block.cpp @@ -68,91 +68,41 @@ unsigned SsaStressHashHelper() } #endif -EHSuccessorIterPosition::EHSuccessorIterPosition(Compiler* comp, BasicBlock* block) - : m_remainingRegSuccs(block->NumSucc(comp)) - , m_numRegSuccs(m_remainingRegSuccs) - , m_curRegSucc(nullptr) - , m_curTry(comp->ehGetBlockExnFlowDsc(block)) +//------------------------------------------------------------------------ +// AllSuccessorEnumerator: Construct an instance of the enumerator. +// +// Arguments: +// comp - Compiler instance +// block - The block whose successors are to be iterated +// +AllSuccessorEnumerator::AllSuccessorEnumerator(Compiler* comp, BasicBlock* block) : m_block(block) { - // If "block" is a "leave helper" block (the empty BBJ_ALWAYS block that pairs with a - // preceding BBJ_CALLFINALLY block to implement a "leave" IL instruction), then no exceptions - // can occur within it, so clear m_curTry if it's non-null. - if (m_curTry != nullptr) - { - if (block->isBBCallAlwaysPairTail()) + m_numSuccs = 0; + block->VisitAllSuccs(comp, [this](BasicBlock* succ) { + if (m_numSuccs < ArrLen(m_successors)) { - m_curTry = nullptr; + m_successors[m_numSuccs] = succ; } - } - - if (m_curTry == nullptr && m_remainingRegSuccs > 0) - { - // Examine the successors to see if any are the start of try blocks. - FindNextRegSuccTry(comp, block); - } -} -void EHSuccessorIterPosition::FindNextRegSuccTry(Compiler* comp, BasicBlock* block) -{ - assert(m_curTry == nullptr); + m_numSuccs++; + return BasicBlockVisit::Continue; + }); - // Must now consider the next regular successor, if any. - while (m_remainingRegSuccs > 0) + if (m_numSuccs > ArrLen(m_successors)) { - m_curRegSucc = block->GetSucc(m_numRegSuccs - m_remainingRegSuccs, comp); - m_remainingRegSuccs--; - if (comp->bbIsTryBeg(m_curRegSucc)) - { - assert(m_curRegSucc->hasTryIndex()); // Since it is a try begin. - unsigned newTryIndex = m_curRegSucc->getTryIndex(); + m_pSuccessors = new (comp, CMK_BasicBlock) BasicBlock*[m_numSuccs]; - // If the try region started by "m_curRegSucc" (represented by newTryIndex) contains m_block, - // we've already yielded its handler, as one of the EH handler successors of m_block itself. - if (comp->bbInExnFlowRegions(newTryIndex, block)) - { - continue; - } + unsigned numSuccs = 0; + block->VisitAllSuccs(comp, [this, &numSuccs](BasicBlock* succ) { + assert(numSuccs < m_numSuccs); + m_pSuccessors[numSuccs++] = succ; + return BasicBlockVisit::Continue; + }); - // Otherwise, consider this try. - m_curTry = comp->ehGetDsc(newTryIndex); - break; - } + assert(numSuccs == m_numSuccs); } } -void EHSuccessorIterPosition::Advance(Compiler* comp, BasicBlock* block) -{ - assert(m_curTry != nullptr); - if (m_curTry->ebdEnclosingTryIndex != EHblkDsc::NO_ENCLOSING_INDEX) - { - m_curTry = comp->ehGetDsc(m_curTry->ebdEnclosingTryIndex); - - // If we've gone over into considering try's containing successors, - // then the enclosing try must have the successor as its first block. - if (m_curRegSucc == nullptr || m_curTry->ebdTryBeg == m_curRegSucc) - { - return; - } - - // Otherwise, give up, try the next regular successor. - m_curTry = nullptr; - } - else - { - m_curTry = nullptr; - } - - // We've exhausted all try blocks. - // See if there are any remaining regular successors that start try blocks. - FindNextRegSuccTry(comp, block); -} - -BasicBlock* EHSuccessorIterPosition::Current(Compiler* comp, BasicBlock* block) -{ - assert(m_curTry != nullptr); - return m_curTry->ExFlowBlock(); -} - FlowEdge* Compiler::BlockPredsWithEH(BasicBlock* blk) { BlockToFlowEdgeMap* ehPreds = GetBlockToEHPreds(); diff --git a/src/coreclr/jit/block.h b/src/coreclr/jit/block.h index 425c5d9d5a892b..2cf6c1518c8d34 100644 --- a/src/coreclr/jit/block.h +++ b/src/coreclr/jit/block.h @@ -199,133 +199,6 @@ struct allMemoryKinds } }; -// This encapsulates the "exception handling" successors of a block. That is, -// if a basic block BB1 occurs in a try block, we consider the first basic block -// BB2 of the corresponding handler to be an "EH successor" of BB1. Because we -// make the conservative assumption that control flow can jump from a try block -// to its handler at any time, the immediate (regular control flow) -// predecessor(s) of the first block of a try block are also considered to -// have the first block of the handler as an EH successor. This makes variables that -// are "live-in" to the handler become "live-out" for these try-predecessor block, -// so that they become live-in to the try -- which we require. -// -// This class maintains the minimum amount of state necessary to implement -// successor iteration. The basic block whose successors are enumerated and -// the compiler need to be provided by Advance/Current's callers. In addition -// to iterators, this allows the use of other approaches that are more space -// efficient. -class EHSuccessorIterPosition -{ - // The number of "regular" (i.e., non-exceptional) successors that remain to - // be considered. If BB1 has successor BB2, and BB2 is the first block of a - // try block, then we consider the catch block of BB2's try to be an EH - // successor of BB1. This captures the iteration over the successors of BB1 - // for this purpose. (In reverse order; we're done when this field is 0). - unsigned m_remainingRegSuccs; - unsigned m_numRegSuccs; - - // The current "regular" successor of "m_block" that we're considering. - BasicBlock* m_curRegSucc; - - // The current try block. If non-null, then the current successor "m_curRegSucc" - // is the first block of the handler of this block. While this try block has - // enclosing try's that also start with "m_curRegSucc", the corresponding handlers will be - // further EH successors. - EHblkDsc* m_curTry; - - // Requires that "m_curTry" is NULL. Determines whether there is, as - // discussed just above, a regular successor that's the first block of a - // try; if so, sets "m_curTry" to that try block. (As noted above, selecting - // the try containing the current regular successor as the "current try" may cause - // multiple first-blocks of catches to be yielded as EH successors: trys enclosing - // the current try are also included if they also start with the current EH successor.) - void FindNextRegSuccTry(Compiler* comp, BasicBlock* block); - -public: - // Constructs a position that "points" to the first EH successor of `block`. - EHSuccessorIterPosition(Compiler* comp, BasicBlock* block); - - // Constructs a position that "points" past the last EH successor of `block` ("end" position). - EHSuccessorIterPosition() : m_remainingRegSuccs(0), m_numRegSuccs(0), m_curTry(nullptr) - { - } - - // Go on to the next EH successor. - void Advance(Compiler* comp, BasicBlock* block); - - // Returns the current EH successor. - // Requires that "*this" is not equal to the "end" position. - BasicBlock* Current(Compiler* comp, BasicBlock* block); - - // Returns "true" iff "*this" is equal to "ehsi". - bool operator==(const EHSuccessorIterPosition& ehsi) - { - return m_curTry == ehsi.m_curTry && m_remainingRegSuccs == ehsi.m_remainingRegSuccs; - } - - bool operator!=(const EHSuccessorIterPosition& ehsi) - { - return !((*this) == ehsi); - } -}; - -// Yields both normal and EH successors (in that order) in one iteration. -// -// This class maintains the minimum amount of state necessary to implement -// successor iteration. The basic block whose successors are enumerated and -// the compiler need to be provided by Advance/Current's callers. In addition -// to iterators, this allows the use of other approaches that are more space -// efficient. -class AllSuccessorIterPosition -{ - // Normal successor position - unsigned m_numNormSuccs; - unsigned m_remainingNormSucc; - // EH successor position - EHSuccessorIterPosition m_ehIter; - - // True iff m_blk is a BBJ_CALLFINALLY block, and the current try block of m_ehIter, - // the first block of whose handler would be next yielded, is the jump target of m_blk. - inline bool CurTryIsBlkCallFinallyTarget(Compiler* comp, BasicBlock* block); - -public: - // Constructs a position that "points" to the first successor of `block`. - inline AllSuccessorIterPosition(Compiler* comp, BasicBlock* block); - - // Constructs a position that "points" past the last successor of `block` ("end" position). - AllSuccessorIterPosition() : m_remainingNormSucc(0), m_ehIter() - { - } - - // Go on to the next successor. - inline void Advance(Compiler* comp, BasicBlock* block); - - // Returns the current successor. - // Requires that "*this" is not equal to the "end" position. - inline BasicBlock* Current(Compiler* comp, BasicBlock* block); - - bool IsCurrentEH() - { - return m_remainingNormSucc == 0; - } - - bool HasCurrent() - { - return *this != AllSuccessorIterPosition(); - } - - // Returns "true" iff "*this" is equal to "asi". - bool operator==(const AllSuccessorIterPosition& asi) - { - return (m_remainingNormSucc == asi.m_remainingNormSucc) && (m_ehIter == asi.m_ehIter); - } - - bool operator!=(const AllSuccessorIterPosition& asi) - { - return !((*this) == asi); - } -}; - // PredEdgeList: adapter class for forward iteration of the predecessor edge linked list using range-based `for`, // normally used via BasicBlock::PredEdges(), e.g.: // for (FlowEdge* const edge : block->PredEdges()) ... @@ -1347,16 +1220,6 @@ struct BasicBlock : private LIR::Range } }; - Successors GetEHSuccs(Compiler* comp) - { - return Successors(comp, this); - } - - Successors GetAllSuccs(Compiler* comp) - { - return Successors(comp, this); - } - template BasicBlockVisit VisitAllSuccs(Compiler* comp, TFunc func); @@ -1988,72 +1851,25 @@ inline PredBlockList::iterator& PredBlockList::iterator::operator++() void* emitCodeGetCookie(BasicBlock* block); -AllSuccessorIterPosition::AllSuccessorIterPosition(Compiler* comp, BasicBlock* block) - : m_numNormSuccs(block->NumSucc(comp)), m_remainingNormSucc(m_numNormSuccs), m_ehIter(comp, block) -{ - if (CurTryIsBlkCallFinallyTarget(comp, block)) - { - m_ehIter.Advance(comp, block); - } -} - -bool AllSuccessorIterPosition::CurTryIsBlkCallFinallyTarget(Compiler* comp, BasicBlock* block) -{ - return (block->bbJumpKind == BBJ_CALLFINALLY) && (m_ehIter != EHSuccessorIterPosition()) && - (block->bbJumpDest == m_ehIter.Current(comp, block)); -} - -void AllSuccessorIterPosition::Advance(Compiler* comp, BasicBlock* block) -{ - if (m_remainingNormSucc > 0) - { - m_remainingNormSucc--; - } - else - { - m_ehIter.Advance(comp, block); - - // If the original block whose successors we're iterating over - // is a BBJ_CALLFINALLY, that finally clause's first block - // will be yielded as a normal successor. Don't also yield as - // an exceptional successor. - if (CurTryIsBlkCallFinallyTarget(comp, block)) - { - m_ehIter.Advance(comp, block); - } - } -} - -// Requires that "this" is not equal to the standard "end" iterator. Returns the -// current successor. -BasicBlock* AllSuccessorIterPosition::Current(Compiler* comp, BasicBlock* block) -{ - if (m_remainingNormSucc > 0) - { - return block->GetSucc(m_numNormSuccs - m_remainingNormSucc, comp); - } - else - { - return m_ehIter.Current(comp, block); - } -} - -typedef BasicBlock::Successors::iterator EHSuccessorIter; -typedef BasicBlock::Successors::iterator AllSuccessorIter; - // An enumerator of a block's all successors. In some cases (e.g. SsaBuilder::TopologicalSort) // using iterators is not exactly efficient, at least because they contain an unnecessary // member - a pointer to the Compiler object. class AllSuccessorEnumerator { - BasicBlock* m_block; - AllSuccessorIterPosition m_pos; + BasicBlock* m_block; + union { + // We store up to 4 successors inline in the enumerator. For ASP.NET + // and libraries.pmi this is enough in 99.7% of cases. + BasicBlock* m_successors[4]; + BasicBlock** m_pSuccessors; + }; + + unsigned m_numSuccs; + unsigned m_curSucc = UINT_MAX; public: // Constructs an enumerator of all `block`'s successors. - AllSuccessorEnumerator(Compiler* comp, BasicBlock* block) : m_block(block), m_pos(comp, block) - { - } + AllSuccessorEnumerator(Compiler* comp, BasicBlock* block); // Gets the block whose successors are enumerated. BasicBlock* Block() @@ -2061,23 +1877,21 @@ class AllSuccessorEnumerator return m_block; } - // Returns true if the next successor is an EH successor. - bool IsNextEHSuccessor() - { - return m_pos.IsCurrentEH(); - } - // Returns the next available successor or `nullptr` if there are no more successors. BasicBlock* NextSuccessor(Compiler* comp) { - if (!m_pos.HasCurrent()) + m_curSucc++; + if (m_curSucc >= m_numSuccs) { return nullptr; } - BasicBlock* succ = m_pos.Current(comp, m_block); - m_pos.Advance(comp, m_block); - return succ; + if (m_numSuccs <= ArrLen(m_successors)) + { + return m_successors[m_curSucc]; + } + + return m_pSuccessors[m_curSucc]; } }; diff --git a/src/coreclr/jit/codegen.h b/src/coreclr/jit/codegen.h index 5d89ef8d01832c..945b082a2dfb39 100644 --- a/src/coreclr/jit/codegen.h +++ b/src/coreclr/jit/codegen.h @@ -257,7 +257,7 @@ class CodeGen final : public CodeGenInterface void genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbered, RegState* regState); #endif void genEnregisterIncomingStackArgs(); -#if defined(TARGET_ARM64) +#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) void genEnregisterOSRArgsAndLocals(regNumber initReg, bool* pInitRegZeroed); #else void genEnregisterOSRArgsAndLocals(); @@ -423,11 +423,11 @@ class CodeGen final : public CodeGenInterface 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_FPRA_save_delta; // FP/RA register save offset from SP (positive) + 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 fiFrameType; // Funclet frame types are numbered. See genFuncletProlog() for details. - int fiSpDelta1; // Stack pointer delta 1 (negative) + int fiSpDelta; // Stack pointer delta (negative) }; FuncletFrameInfoDsc genFuncletInfo; diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index 0d0aa1a2ed2999..eaf16b49be7ee3 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -4655,7 +4655,7 @@ void CodeGen::genZeroInitFrame(int untrLclHi, int untrLclLo, regNumber initReg, // initReg -- scratch register to use if needed // pInitRegZeroed -- [IN,OUT] if init reg is zero (on entry/exit) // -#if defined(TARGET_ARM64) +#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) void CodeGen::genEnregisterOSRArgsAndLocals(regNumber initReg, bool* pInitRegZeroed) #else void CodeGen::genEnregisterOSRArgsAndLocals() @@ -4796,7 +4796,7 @@ void CodeGen::genEnregisterOSRArgsAndLocals() GetEmitter()->emitIns_R_AR(ins_Load(lclTyp), size, varDsc->GetRegNum(), genFramePointerReg(), offset); -#elif defined(TARGET_ARM64) +#elif defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) // Patchpoint offset is from top of Tier0 frame // @@ -5436,7 +5436,7 @@ void CodeGen::genFnProlog() psiBegProlog(); } -#if defined(TARGET_ARM64) +#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) // For arm64 OSR, emit a "phantom prolog" to account for the actions taken // in the tier0 frame that impact FP and SP on entry to the OSR method. // @@ -5451,7 +5451,7 @@ void CodeGen::genFnProlog() // SP is tier0 method's SP. compiler->unwindAllocStack(tier0FrameSize); } -#endif // defined(TARGET_ARM64) +#endif // defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) #ifdef DEBUG @@ -5774,6 +5774,14 @@ void CodeGen::genFnProlog() { initReg = REG_IP1; } +#elif defined(TARGET_LOONGARCH64) + // For loongarch64 OSR root frames, we may need a scratch register for large + // offset addresses. Use a register that won't be allocated. + // + if (isRoot && compiler->opts.IsOSR()) + { + initReg = REG_SCRATCH; + } #endif noway_assert(!compiler->compMethodRequiresPInvokeFrame() || (initReg != REG_PINVOKE_FRAME)); @@ -6087,7 +6095,7 @@ void CodeGen::genFnProlog() // Otherwise we'll do some of these fetches twice. // CLANG_FORMAT_COMMENT_ANCHOR; -#if defined(TARGET_ARM64) +#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) genEnregisterOSRArgsAndLocals(initReg, &initRegZeroed); #else genEnregisterOSRArgsAndLocals(); diff --git a/src/coreclr/jit/codegeninterface.h b/src/coreclr/jit/codegeninterface.h index 1f8f4c6b0c7fe4..c2bcedb8ea9b7e 100644 --- a/src/coreclr/jit/codegeninterface.h +++ b/src/coreclr/jit/codegeninterface.h @@ -127,7 +127,9 @@ class CodeGenInterface #define INST_FP 0x01 // is it a FP instruction? public: static bool instIsFP(instruction ins); - +#if defined(TARGET_XARCH) + static bool instIsEmbeddedBroadcastCompatible(instruction ins); +#endif // TARGET_XARCH //------------------------------------------------------------------------- // Liveness-related fields & methods public: @@ -764,6 +766,10 @@ class CodeGenInterface virtual const char* siStackVarName(size_t offs, size_t size, unsigned reg, unsigned stkOffs) = 0; #endif // LATE_DISASM + +#if defined(TARGET_XARCH) + bool IsEmbeddedBroadcastEnabled(instruction ins, GenTree* op); +#endif }; #endif // _CODEGEN_INTERFACE_H_ diff --git a/src/coreclr/jit/codegenloongarch64.cpp b/src/coreclr/jit/codegenloongarch64.cpp index 1617b7d24262ae..3135507a05c217 100644 --- a/src/coreclr/jit/codegenloongarch64.cpp +++ b/src/coreclr/jit/codegenloongarch64.cpp @@ -20,6 +20,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #include "lower.h" #include "gcinfo.h" #include "gcinfoencoder.h" +#include "patchpointinfo.h" /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX @@ -271,7 +272,7 @@ void CodeGen::genPrologSaveReg(regNumber reg1, int spOffset, int spDelta, regNum if (spDelta != 0) { - // generate daddiu SP,SP,-imm + // generate addi.d SP,SP,-imm genStackPointerAdjustment(spDelta, tmpReg, pTmpRegIsZero, /* reportUnwindData */ true); } @@ -330,7 +331,7 @@ void CodeGen::genEpilogRestoreRegPair(regNumber reg1, GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg1, REG_SPBASE, spOffset); compiler->unwindSaveReg(reg1, spOffset); - // generate daddiu SP,SP,imm + // generate addi.d SP,SP,imm genStackPointerAdjustment(spDelta, tmpReg, pTmpRegIsZero, /* reportUnwindData */ true); } else @@ -372,11 +373,11 @@ void CodeGen::genEpilogRestoreReg(regNumber reg1, int spOffset, int spDelta, reg if (spDelta != 0) { - // ld reg1, offset(SP) + // ld.d reg1,SP,offset GetEmitter()->emitIns_R_R_I(ins, EA_PTRSIZE, reg1, REG_SPBASE, spOffset); compiler->unwindSaveReg(reg1, spOffset); - // generate add SP,SP,imm + // generate addi.d SP,SP,imm genStackPointerAdjustment(spDelta, tmpReg, pTmpRegIsZero, /* reportUnwindData */ true); } else @@ -675,25 +676,15 @@ void CodeGen::genRestoreCalleeSavedRegisterGroup(regMaskTP regsMask, int spDelta // zero). // // Here's an example restore sequence: -// ld s7, 88(sp) -// ld s6, 80(sp) -// ld s5, 72(sp) -// ld s4, 64(sp) -// ld s3, 56(sp) -// ld s2, 48(sp) -// ld s1, 40(sp) -// ld s0, 32(sp) -// -// For the case of non-zero spDelta, we assume the base of the callee-save registers to restore is at SP, and -// the last restore adjusts SP by the specified amount. For example: -// ld s7, 56(sp) -// ld s6, 48(sp) -// ld s5, 40(sp) -// ld s4, 32(sp) -// ld s3, 24(sp) -// ld s2, 16(sp) -// ld s1, 88(sp) -// ld s0, 80(sp) +// ld.d s8,sp,#xxx +// ld.d s7,sp,#xxx +// ld.d s6,sp,#xxx +// ld.d s5,sp,#xxx +// ld.d s4,sp,#xxx +// ld.d s3,sp,#xxx +// ld.d s2,sp,#xxx +// ld.d s1,sp,#xxx +// ld.d s0,sp,#xxx // // Note you call the unwind functions specifying the prolog operation that is being un-done. So, for example, when // generating a post-indexed load, you call the unwind function for specifying the corresponding preindexed store. @@ -754,142 +745,45 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * * Funclets have the following incoming arguments: * - * catch: a0 = the exception object that was caught (see GT_CATCH_ARG) - * filter: a0 = the exception object to filter (see GT_CATCH_ARG), a1 = CallerSP of the containing function - * finally/fault: none + * catch: a0 = the exception object that was caught (see GT_CATCH_ARG) + * filter: a0 = the exception object to filter (see GT_CATCH_ARG), a1 = CallerSP of the containing function + * finally/fault: none * * Funclets set the following registers on exit: * - * catch: v0 = the address at which execution should resume (see BBJ_EHCATCHRET) - * filter: v0 = non-zero if the handler should handle the exception, zero otherwise (see GT_RETFILT) - * finally/fault: none + * catch: a0 = the address at which execution should resume (see BBJ_EHCATCHRET) + * filter: a0 = non-zero if the handler should handle the exception, zero otherwise (see GT_RETFILT) + * finally/fault: none * - * The LOONGARCH64 funclet prolog sequence is one of 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 1: - * For #framesz <= 32760 and FP/RA at bottom: - * daddiu sp,sp,-#framesz ; establish the frame (predecrement by #framesz), save FP/RA - * sd fp,#outsz(sp) - * sd ra,#outsz+8(sp) - * sd s0,#xxx-8(sp) ; save callee-saved registers, as necessary - * sd s1,#xxx(sp) + * Frame type liking: + * addi_d sp,sp,-#framesz ; establish the frame, maybe multi-instruction. + * st.d s0,sp,#outsz ; save callee-saved registers, as necessary + * st.d s1,sp,#outsz+8 + * st.d ra,sp,#outsz+? + * st.d fp,sp,#outsz+? * - * The funclet frame is thus: + * The funclet frame layout: * * | | * |-----------------------| * | incoming arguments | * +=======================+ <---- Caller's SP - * | Varargs regs space | // Only for varargs main functions; 64 bytes - * |-----------------------| - * |Callee saved registers | // multiple of 8 bytes - * |-----------------------| - * | PSP slot | // 8 bytes (omitted in NativeAOT ABI) - * |-----------------------| - * ~ alignment padding ~ // To make the whole frame 16 byte aligned. + * | OSR padding | // If required * |-----------------------| - * | Saved FP, RA | // 16 bytes - * |-----------------------| - * | Outgoing arg space | // multiple of 8 bytes; if required (i.e., #outsz != 0) - * |-----------------------| <---- Ambient SP - * | | | - * ~ | Stack grows ~ - * | | downward | - * V - * - * Frame type 2: - * For #framesz <= 32760 and FP/RA at top: - * daddiu sp,sp,-#framesz ; establish the frame - * sd s0,xxx(sp) ; save callee-saved registers, as necessary - * sd s1,xxx+8(sp) - * sd s?,xxx+?(sp) - * sd fp,xxx+?(sp) ; save FP/RA. - * sd ra,xxx+?(sp) - * - * The funclet frame is thus: - * - * | | - * |-----------------------| - * | incoming arguments | - * +=======================+ <---- Caller's SP * | Varargs regs space | // Only for varargs main functions; 64 bytes * |-----------------------| - * | Saved FP, RA | // 16 bytes - * |-----------------------| - * |Callee saved registers | // multiple of 8 bytes + * | MonitorAcquired | // 8 bytes; for synchronized methods * |-----------------------| * | PSP slot | // 8 bytes (omitted in NativeAOT ABI) * |-----------------------| - * ~ 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 - * | | | - * ~ | Stack grows ~ - * | | downward | - * V - * - * Frame type 3: - * For #framesz > 32760 and FP/RA at bottom: - * ; for funclet, #framesz-#outsz will be less than 32760. - * - * daddiu sp,sp,-(#framesz-#FPRA_delta) ; note maybe 16byte-alignment. - * sd fp, pad(sp) ; pad is depended on stack-16byte-alignment.. - * sd ra, pad+8(sp) - * sd s0,#xxx(sp) ; save callee-saved registers, as necessary, - * sd s1,#xxx+8(sp) - * daddiu sp,sp,-#outsz ; create space for outgoing argument space, maybe 16byte-alignment. - * - * The funclet frame is thus: - * - * | | - * |-----------------------| - * | incoming arguments | - * +=======================+ <---- Caller's SP - * | Varargs regs space | // Only for varargs main functions; 64 bytes - * |-----------------------| - * |Callee saved registers | // multiple of 8 bytes - * |-----------------------| - * | PSP slot | // 8 bytes (omitted in NativeAOT ABI) - * |-----------------------| - * ~ alignment padding ~ + * ~ alignment padding ~ // To make the whole frame 16 byte aligned * |-----------------------| * | Saved FP, RA | // 16 bytes * |-----------------------| - * | Outgoing arg space | // multiple of 8 bytes - * |-----------------------| <---- Ambient SP - * | | | - * ~ | Stack grows ~ - * | | downward | - * V - * - * Frame type 4: - * For #framesz > 32760 and FP/RA at top: - * daddiu sp,sp,-#framesz+PSP_offset ; establish the frame, maybe 16byte-alignment. - * sd s0,xxx(sp) ; save callee-saved registers, as necessary - * sd s1,xxx+8(sp) - * sd s?,xxx+?(sp) - * sd fp,xxx+?(sp) ; save FP/RA. - * sd ra,xxx+?(sp) - * - * daddiu sp,sp,-#PSP_offset ; establish the frame, maybe 16byte-alignment. - * - * The funclet frame is thus: - * - * | | - * |-----------------------| - * | incoming arguments | - * +=======================+ <---- Caller's SP - * | Varargs regs space | // Only for varargs main functions; 64 bytes - * |-----------------------| - * | Saved FP, RA | // 16 bytes - * |-----------------------| - * |Callee saved registers | // multiple of 8 bytes - * |-----------------------| - * | 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 includting FP/RA * |-----------------------| * | Outgoing arg space | // multiple of 8 bytes; if required (i.e., #outsz != 0) * |-----------------------| <---- Ambient SP @@ -906,10 +800,9 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * 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 + * 8 saved integer argument registers a0-a7, if varargs function support. * 1 PSP slot - * 1 alignment slot, future maybe add gp - * == 29 slots * 8 bytes = 232 bytes. + * == 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 @@ -956,28 +849,28 @@ void CodeGen::genRestoreCalleeSavedRegistersHelp(regMaskTP regsToRestoreMask, in * // be a funclet or main function. We won't know any time there is a filter protecting nested EH. To simplify, we just always * // create a main function PSP for any function with a filter. * - * ld a1, CallerSP_to_PSP_slot_delta(a1) ; Load the CallerSP of the main function (stored in the PSP of the dynamically containing funclet or function) - * sd a1, SP_to_PSP_slot_delta(sp) ; store the PSP - * daddiu fp, a1, Function_CallerSP_to_FP_delta ; re-establish the frame pointer + * ld.d a1,a1, CallerSP_to_PSP_slot_delta ; Load the CallerSP of the main function (stored in the PSP of the dynamically containing funclet or function) + * st.d a1,sp, SP_to_PSP_slot_delta ; store the PSP + * addi.d fp, a1, Function_CallerSP_to_FP_delta ; re-establish the frame pointer * } * else * { * // This is NOT a filter funclet. The VM re-establishes the frame pointer on entry. * // TODO-LOONGARCH64-CQ: if VM set a1 to CallerSP on entry, like for filters, we could save an instruction. * - * daddiu a3, fp, Function_FP_to_CallerSP_delta ; compute the CallerSP, given the frame pointer. a3 is scratch? - * sd a3, SP_to_PSP_slot_delta(sp) ; store the PSP + * addi.d a3,fp,Function_FP_to_CallerSP_delta ; compute the CallerSP, given the frame pointer. a3 is scratch? + * st.d a3,sp,SP_to_PSP_slot_delta ; store the PSP * } * * An example epilog sequence is then: * - * daddiu sp,sp,#outsz ; if any outgoing argument space + * addi.d sp,sp,#outsz ; if any outgoing argument space * ... ; restore callee-saved registers - * ld s0,#xxx-8(sp) - * ld s1,#xxx(sp) - * ld fp,#framesz-8(sp) - * ld ra,#framesz(sp) - * daddiu sp,sp,#framesz + * ld.d s0,sp,#xxx-8 + * ld.d s1,sp,#xxx + * ld.d ra,sp,#xxx+? + * ld.d fp,sp,#xxx+? + * addi.d sp,sp,#framesz * jr ra * */ @@ -999,15 +892,9 @@ void CodeGen::genFuncletProlog(BasicBlock* block) compiler->unwindBegProlog(); - regMaskTP maskSaveRegsFloat = genFuncletInfo.fiSaveRegs & RBM_ALLFLOAT; - regMaskTP maskSaveRegsInt = genFuncletInfo.fiSaveRegs & ~maskSaveRegsFloat; - - // Funclets must always save RA and FP, since when we have funclets we must have an FP frame. - assert((maskSaveRegsInt & RBM_RA) != 0); - assert((maskSaveRegsInt & RBM_FP) != 0); - bool isFilter = (block->bbCatchTyp == BBCT_FILTER); - int frameSize = genFuncletInfo.fiSpDelta1; + int frameSize = genFuncletInfo.fiSpDelta; + assert(frameSize < 0); regMaskTP maskArgRegsLiveIn; if (isFilter) @@ -1023,62 +910,42 @@ void CodeGen::genFuncletProlog(BasicBlock* block) maskArgRegsLiveIn = RBM_A0; } -#ifdef DEBUG - if (compiler->opts.disAsm) - { - printf("DEBUG: CodeGen::genFuncletProlog, frameType:%d\n\n", genFuncletInfo.fiFrameType); - } -#endif + regMaskTP maskSaveRegs = genFuncletInfo.fiSaveRegs & RBM_CALLEE_SAVED; + int regsSavedSize = (compiler->compCalleeRegsPushed - 2) << 3; - int offset = 0; - if (genFuncletInfo.fiFrameType == 1) + int SP_to_CalleeSaved_delta = genFuncletInfo.fiSP_to_CalleeSaved_delta; + if ((SP_to_CalleeSaved_delta + regsSavedSize + genFuncletInfo.fiCalleeSavedPadding) <= 2040) { - // fiFrameType constraints: - assert(frameSize < 0); - assert(frameSize >= -2048); + SP_to_CalleeSaved_delta += genFuncletInfo.fiCalleeSavedPadding; - assert(genFuncletInfo.fiSP_to_FPRA_save_delta < 2040); genStackPointerAdjustment(frameSize, REG_R21, nullptr, /* reportUnwindData */ true); - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_FP, REG_SPBASE, genFuncletInfo.fiSP_to_FPRA_save_delta); - compiler->unwindSaveReg(REG_FP, genFuncletInfo.fiSP_to_FPRA_save_delta); + genSaveCalleeSavedRegistersHelp(maskSaveRegs, SP_to_CalleeSaved_delta, 0); + SP_to_CalleeSaved_delta += regsSavedSize; - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_RA, REG_SPBASE, - genFuncletInfo.fiSP_to_FPRA_save_delta + 8); - compiler->unwindSaveReg(REG_RA, genFuncletInfo.fiSP_to_FPRA_save_delta + 8); + 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); - maskSaveRegsInt &= ~(RBM_RA | RBM_FP); // We've saved these now - - genSaveCalleeSavedRegistersHelp(maskSaveRegsInt | maskSaveRegsFloat, genFuncletInfo.fiSP_to_PSP_slot_delta + 8, - 0); + 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); } - else if (genFuncletInfo.fiFrameType == 2) + else { - // fiFrameType constraints: - assert(frameSize < -2048); + assert(frameSize < -2040); - offset = -frameSize - genFuncletInfo.fiSP_to_FPRA_save_delta; - int SP_delta = roundUp((UINT)offset, STACK_ALIGN); - offset = SP_delta - offset; - - genStackPointerAdjustment(-SP_delta, REG_R21, nullptr, /* reportUnwindData */ true); - - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_FP, REG_SPBASE, offset); - compiler->unwindSaveReg(REG_FP, offset); + int SP_delta = frameSize + SP_to_CalleeSaved_delta; + genStackPointerAdjustment(SP_delta, REG_R21, nullptr, /* reportUnwindData */ true); - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_RA, REG_SPBASE, offset + 8); - compiler->unwindSaveReg(REG_RA, offset + 8); + genSaveCalleeSavedRegistersHelp(maskSaveRegs, genFuncletInfo.fiCalleeSavedPadding, 0); + regsSavedSize += genFuncletInfo.fiCalleeSavedPadding; - maskSaveRegsInt &= ~(RBM_RA | RBM_FP); // We've saved these now + GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_RA, REG_SPBASE, regsSavedSize); + compiler->unwindSaveReg(REG_RA, regsSavedSize); - offset = frameSize + SP_delta + genFuncletInfo.fiSP_to_PSP_slot_delta + 8; - genSaveCalleeSavedRegistersHelp(maskSaveRegsInt | maskSaveRegsFloat, offset, 0); + GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_FP, REG_SPBASE, regsSavedSize + 8); + compiler->unwindSaveReg(REG_FP, regsSavedSize + 8); - genStackPointerAdjustment(frameSize + SP_delta, REG_R21, nullptr, /* reportUnwindData */ true); - } - else - { - unreached(); + genStackPointerAdjustment(-SP_to_CalleeSaved_delta, REG_R21, nullptr, /* reportUnwindData */ true); } // This is the end of the OS-reported prolog for purposes of unwinding @@ -1140,84 +1007,47 @@ void CodeGen::genFuncletEpilog() ScopedSetVariable _setGeneratingEpilog(&compiler->compGeneratingEpilog, true); - bool unwindStarted = false; - int frameSize = genFuncletInfo.fiSpDelta1; - - if (!unwindStarted) - { - // We can delay this until we know we'll generate an unwindable instruction, if necessary. - compiler->unwindBegEpilog(); - unwindStarted = true; - } - - regMaskTP maskRestoreRegsFloat = genFuncletInfo.fiSaveRegs & RBM_ALLFLOAT; - regMaskTP maskRestoreRegsInt = genFuncletInfo.fiSaveRegs & ~maskRestoreRegsFloat; - - // Funclets must always save RA and FP, since when we have funclets we must have an FP frame. - assert((maskRestoreRegsInt & RBM_RA) != 0); - assert((maskRestoreRegsInt & RBM_FP) != 0); - -#ifdef DEBUG - if (compiler->opts.disAsm) - { - printf("DEBUG: CodeGen::genFuncletEpilog, frameType:%d\n\n", genFuncletInfo.fiFrameType); - } -#endif - - regMaskTP regsToRestoreMask = maskRestoreRegsInt | maskRestoreRegsFloat; + compiler->unwindBegEpilog(); + int frameSize = genFuncletInfo.fiSpDelta; assert(frameSize < 0); - if (genFuncletInfo.fiFrameType == 1) - { - // fiFrameType constraints: - assert(frameSize >= -2048); - assert(genFuncletInfo.fiSP_to_FPRA_save_delta < 2040); - regsToRestoreMask &= ~(RBM_RA | RBM_FP); // We restore FP/RA at the end + regMaskTP regsToRestoreMask = genFuncletInfo.fiSaveRegs & RBM_CALLEE_SAVED; + int regsRestoreSize = (compiler->compCalleeRegsPushed - 2) << 3; - genRestoreCalleeSavedRegistersHelp(regsToRestoreMask, genFuncletInfo.fiSP_to_PSP_slot_delta + 8, 0); + int SP_to_CalleeSaved_delta = genFuncletInfo.fiSP_to_CalleeSaved_delta; + if ((SP_to_CalleeSaved_delta + regsRestoreSize + genFuncletInfo.fiCalleeSavedPadding) <= 2040) + { + 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, - genFuncletInfo.fiSP_to_FPRA_save_delta + 8); - compiler->unwindSaveReg(REG_RA, genFuncletInfo.fiSP_to_FPRA_save_delta + 8); + 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); - GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_FP, REG_SPBASE, genFuncletInfo.fiSP_to_FPRA_save_delta); - compiler->unwindSaveReg(REG_FP, genFuncletInfo.fiSP_to_FPRA_save_delta); + 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); - // generate daddiu SP,SP,imm genStackPointerAdjustment(-frameSize, REG_R21, nullptr, /* reportUnwindData */ true); } - else if (genFuncletInfo.fiFrameType == 2) + else { - // fiFrameType constraints: - assert(frameSize < -2048); - - int offset = -frameSize - genFuncletInfo.fiSP_to_FPRA_save_delta; - int SP_delta = roundUp((UINT)offset, STACK_ALIGN); - offset = SP_delta - offset; - - // first, generate daddiu SP,SP,imm - genStackPointerAdjustment(-frameSize - SP_delta, REG_R21, nullptr, /* reportUnwindData */ true); + assert(frameSize < -2040); - int offset2 = frameSize + SP_delta + genFuncletInfo.fiSP_to_PSP_slot_delta + 8; - assert(offset2 < 2040); // can amend. + genStackPointerAdjustment(SP_to_CalleeSaved_delta, REG_R21, nullptr, /* reportUnwindData */ true); - regsToRestoreMask &= ~(RBM_RA | RBM_FP); // We restore FP/RA at the end - genRestoreCalleeSavedRegistersHelp(regsToRestoreMask, offset2, 0); + genRestoreCalleeSavedRegistersHelp(regsToRestoreMask, genFuncletInfo.fiCalleeSavedPadding, 0); + regsRestoreSize += genFuncletInfo.fiCalleeSavedPadding; - GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_RA, REG_SPBASE, offset + 8); - compiler->unwindSaveReg(REG_RA, offset + 8); + 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_FP, REG_SPBASE, offset); - compiler->unwindSaveReg(REG_FP, offset); + GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_FP, REG_SPBASE, regsRestoreSize + 8); + compiler->unwindSaveReg(REG_FP, regsRestoreSize + 8); - // second, generate daddiu SP,SP,imm for remaine space. - genStackPointerAdjustment(SP_delta, REG_R21, nullptr, /* reportUnwindData */ true); - } - else - { - unreached(); + genStackPointerAdjustment(-frameSize - SP_to_CalleeSaved_delta, 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); @@ -1246,61 +1076,62 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() // The frame size and offsets must be finalized assert(compiler->lvaDoneFrameLayout == Compiler::FINAL_FRAME_LAYOUT); - genFuncletInfo.fiFunction_CallerSP_to_FP_delta = genCallerSPtoFPdelta(); - regMaskTP rsMaskSaveRegs = regSet.rsMaskCalleeSaved; assert((rsMaskSaveRegs & RBM_RA) != 0); assert((rsMaskSaveRegs & RBM_FP) != 0); unsigned PSPSize = (compiler->lvaPSPSym != BAD_VAR_NUM) ? 8 : 0; - unsigned saveRegsCount = genCountBits(rsMaskSaveRegs); - assert((saveRegsCount == compiler->compCalleeRegsPushed) || (saveRegsCount == compiler->compCalleeRegsPushed - 1)); + // 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)) + { + 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 saveRegsPlusPSPSize = - roundUp((UINT)genTotalFrameSize(), STACK_ALIGN) - compiler->compLclFrameSize + PSPSize; + unsigned regsSavedSize = genCountBits(rsMaskSaveRegs) << 3; + assert(genCountBits(rsMaskSaveRegs) == compiler->compCalleeRegsPushed); - unsigned saveRegsPlusPSPSizeAligned = roundUp(saveRegsPlusPSPSize, STACK_ALIGN); + unsigned saveRegsPlusPSPSize = regsSavedSize + PSPSize; assert(compiler->lvaOutgoingArgSpaceSize % REGSIZE_BYTES == 0); unsigned outgoingArgSpaceAligned = roundUp(compiler->lvaOutgoingArgSpaceSize, STACK_ALIGN); - unsigned maxFuncletFrameSizeAligned = saveRegsPlusPSPSizeAligned + outgoingArgSpaceAligned; - assert((maxFuncletFrameSizeAligned % STACK_ALIGN) == 0); - - int SP_to_FPRA_save_delta = compiler->lvaOutgoingArgSpaceSize; - - unsigned funcletFrameSize = saveRegsPlusPSPSize + compiler->lvaOutgoingArgSpaceSize; + unsigned funcletFrameSize = osrPad + saveRegsPlusPSPSize + compiler->lvaOutgoingArgSpaceSize; unsigned funcletFrameSizeAligned = roundUp(funcletFrameSize, STACK_ALIGN); - assert(funcletFrameSizeAligned <= maxFuncletFrameSizeAligned); - unsigned funcletFrameAlignmentPad = funcletFrameSizeAligned - funcletFrameSize; - assert((funcletFrameAlignmentPad == 0) || (funcletFrameAlignmentPad == REGSIZE_BYTES)); - - if (maxFuncletFrameSizeAligned <= (2048 - 8)) + int SP_to_CalleeSaved_delta = compiler->lvaOutgoingArgSpaceSize; + if ((SP_to_CalleeSaved_delta + regsSavedSize) >= 2040) { - genFuncletInfo.fiFrameType = 1; - saveRegsPlusPSPSize -= 2 * 8; // FP/RA - } - else - { - unsigned saveRegsPlusPSPAlignmentPad = saveRegsPlusPSPSizeAligned - saveRegsPlusPSPSize; - assert((saveRegsPlusPSPAlignmentPad == 0) || (saveRegsPlusPSPAlignmentPad == REGSIZE_BYTES)); + int offset = funcletFrameSizeAligned - SP_to_CalleeSaved_delta; + SP_to_CalleeSaved_delta = AlignUp((UINT)offset, STACK_ALIGN); - genFuncletInfo.fiFrameType = 2; - saveRegsPlusPSPSize -= 2 * 8; // FP/RA + genFuncletInfo.fiCalleeSavedPadding = SP_to_CalleeSaved_delta - offset; } - int CallerSP_to_PSP_slot_delta = -(int)saveRegsPlusPSPSize; - genFuncletInfo.fiSpDelta1 = -(int)funcletFrameSizeAligned; - int SP_to_PSP_slot_delta = funcletFrameSizeAligned - saveRegsPlusPSPSize; + 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); + } /* Now save it for future use */ - genFuncletInfo.fiSaveRegs = rsMaskSaveRegs; - genFuncletInfo.fiSP_to_FPRA_save_delta = SP_to_FPRA_save_delta; + genFuncletInfo.fiSpDelta = -(int)funcletFrameSizeAligned; + genFuncletInfo.fiSaveRegs = rsMaskSaveRegs; + genFuncletInfo.fiSP_to_CalleeSaved_delta = SP_to_CalleeSaved_delta; - genFuncletInfo.fiSP_to_PSP_slot_delta = SP_to_PSP_slot_delta; - genFuncletInfo.fiCallerSP_to_PSP_slot_delta = CallerSP_to_PSP_slot_delta; + genFuncletInfo.fiSP_to_PSP_slot_delta = funcletFrameSizeAligned - osrPad - 8; + genFuncletInfo.fiCallerSP_to_PSP_slot_delta = -(int)osrPad - 8; #ifdef DEBUG if (verbose) @@ -1310,23 +1141,22 @@ void CodeGen::genCaptureFuncletPrologEpilogInfo() printf(" Save regs: "); dspRegMask(genFuncletInfo.fiSaveRegs); printf("\n"); - printf(" Function CallerSP-to-FP delta: %d\n", genFuncletInfo.fiFunction_CallerSP_to_FP_delta); - printf(" SP to FP/RA save location delta: %d\n", genFuncletInfo.fiSP_to_FPRA_save_delta); - printf(" Frame type: %d\n", genFuncletInfo.fiFrameType); - printf(" SP delta 1: %d\n", genFuncletInfo.fiSpDelta1); - - if (compiler->lvaPSPSym != BAD_VAR_NUM) + if (compiler->opts.IsOSR()) { - if (CallerSP_to_PSP_slot_delta != - compiler->lvaGetCallerSPRelativeOffset(compiler->lvaPSPSym)) // for debugging - { - printf("lvaGetCallerSPRelativeOffset(lvaPSPSym): %d\n", - compiler->lvaGetCallerSPRelativeOffset(compiler->lvaPSPSym)); - } + printf(" OSR Pad: %d\n", osrPad); } + 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); } + assert(genFuncletInfo.fiSP_to_CalleeSaved_delta >= 0); - assert(genFuncletInfo.fiSP_to_FPRA_save_delta >= 0); + if (compiler->lvaPSPSym != BAD_VAR_NUM) + { + assert(genFuncletInfo.fiCallerSP_to_PSP_slot_delta == + compiler->lvaGetCallerSPRelativeOffset(compiler->lvaPSPSym)); // same offset used in main function and + // funclet! + } #endif // DEBUG } @@ -1511,12 +1341,17 @@ void CodeGen::genSetPSPSym(regNumber initReg, bool* pInitRegZeroed) int SPtoCallerSPdelta = -genCallerSPtoInitialSPdelta(); + if (compiler->opts.IsOSR()) + { + SPtoCallerSPdelta += compiler->info.compPatchpointInfo->TotalFrameSize(); + } + // We will just use the initReg since it is an available register // and we are probably done using it anyway... regNumber regTmp = initReg; *pInitRegZeroed = false; - genInstrWithConstant(INS_addi_d, EA_PTRSIZE, regTmp, REG_SPBASE, SPtoCallerSPdelta, REG_R21, false); + genInstrWithConstant(INS_addi_d, EA_PTRSIZE, regTmp, REG_SPBASE, SPtoCallerSPdelta, regTmp, false); GetEmitter()->emitIns_S_R(INS_st_d, EA_PTRSIZE, regTmp, compiler->lvaPSPSym, 0); } @@ -1806,7 +1641,7 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre emitAttr size = emitActualTypeSize(tree); double constValue = tree->AsDblCon()->DconValue(); - // Make sure we use "daddiu reg, zero, 0x00" only for positive zero (0.0) + // 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) { @@ -2867,8 +2702,8 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node) // GC pointers. // For this case we'll generate a sequence of loads/stores in the case of struct // slots that don't contain GC pointers. The generated code will look like: -// ld tempReg, 8(A5) -// sd tempReg, 8(A6) +// ld.d tempReg,A5,8 +// st.d tempReg,A6,8 // // In the case of a GC-Pointer we'll call the ByRef write barrier helper // who happens to use the same registers as the previous call to maintain @@ -2876,14 +2711,14 @@ void CodeGen::genCodeForInitBlkUnroll(GenTreeBlk* node) // bl CORINFO_HELP_ASSIGN_BYREF // // So finally an example would look like this: -// ld tempReg, 8(A5) -// sd tempReg, 8(A6) +// ld.d tempReg,A5,8 +// st.d tempReg,A6,8 // bl CORINFO_HELP_ASSIGN_BYREF -// ld tempReg, 8(A5) -// sd tempReg, 8(A6) +// ld.d tempReg,A5,8 +// st.d tempReg,A6,8 // bl CORINFO_HELP_ASSIGN_BYREF -// ld tempReg, 8(A5) -// sd tempReg, 8(A6) +// ld.d tempReg,A5,8 +// st.d tempReg,A6,8 void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) { GenTree* dstAddr = cpObjNode->Addr(); @@ -2955,7 +2790,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) if (dstOnStack) { unsigned i = 0; - // Check if two or more remaining slots and use two ld/sd sequence + // Check if two or more remaining slots and use two load/store sequence while (i < slots - 1) { emitAttr attr0 = emitTypeSize(layout->GetGCPtrType(i + 0)); @@ -2977,7 +2812,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) i += 2; } - // Use a ld/sd sequence for the last remainder + // Use a load/store sequence for the last remainder if (i < slots) { emitAttr attr0 = emitTypeSize(layout->GetGCPtrType(i + 0)); @@ -3004,7 +2839,7 @@ void CodeGen::genCodeForCpObj(GenTreeBlk* cpObjNode) { if (!layout->IsGCPtr(i)) { - // Check if the next slot's type is also TYP_GC_NONE and use two ld/sd + // Check if the next slot's type is also TYP_GC_NONE and use two load/store if ((i + 1 < slots) && !layout->IsGCPtr(i + 1)) { if ((i + 2) == slots) @@ -4078,29 +3913,6 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) assert(targetReg != REG_NA); assert(tree->TypeGet() != TYP_VOID); - if (op1->isContainedIntOrIImmed()) - { - op1 = tree->gtOp2; - op2 = tree->gtOp1; - switch (tree->OperGet()) - { - case GT_LT: - tree->SetOper(GT_GT); - break; - case GT_LE: - tree->SetOper(GT_GE); - break; - case GT_GT: - tree->SetOper(GT_LT); - break; - case GT_GE: - tree->SetOper(GT_LE); - break; - default: - break; - } - } - assert(!op1->isContainedIntOrIImmed()); assert(tree->OperIs(GT_LT, GT_LE, GT_EQ, GT_NE, GT_GT, GT_GE)); @@ -4120,6 +3932,7 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) if (IsUnsigned) { imm = static_cast(imm); + emit->emitIns_R_R_I_I(INS_bstrpick_d, EA_8BYTE, tmpRegOp1, regOp1, 31, 0); } else @@ -4355,19 +4168,18 @@ void CodeGen::genCodeForJumpCompare(GenTreeOpCC* tree) { case EA_4BYTE: { - regNumber tmpRegOp1 = REG_R21; - assert(regOp1 != tmpRegOp1); + assert(regOp1 != REG_R21); if (cond.IsUnsigned()) { imm = static_cast(imm); - emit->emitIns_R_R_I_I(INS_bstrpick_d, EA_8BYTE, tmpRegOp1, regOp1, 31, 0); + emit->emitIns_R_R_I_I(INS_bstrpick_d, EA_8BYTE, REG_R21, regOp1, 31, 0); } else { imm = static_cast(imm); - emit->emitIns_R_R_I(INS_slli_w, EA_4BYTE, tmpRegOp1, regOp1, 0); + emit->emitIns_R_R_I(INS_slli_w, EA_4BYTE, REG_R21, regOp1, 0); } - regOp1 = tmpRegOp1; + regOp1 = REG_R21; break; } case EA_8BYTE: @@ -4389,6 +4201,22 @@ void CodeGen::genCodeForJumpCompare(GenTreeOpCC* tree) emit->emitIns_I_la(EA_PTRSIZE, REG_RA, imm); regs = (int)REG_RA << 5; } + else + { + if (cmpSize == EA_4BYTE) + { + assert(regOp1 != REG_R21); + if (cond.IsUnsigned()) + { + emit->emitIns_R_R_I_I(INS_bstrpick_d, EA_8BYTE, REG_R21, regOp1, 31, 0); + } + else + { + emit->emitIns_R_R_I(INS_slli_w, EA_8BYTE, REG_R21, regOp1, 0); + } + regOp1 = REG_R21; + } + } switch (cond.GetCode()) { @@ -4498,8 +4326,9 @@ void CodeGen::genCodeForJumpCompare(GenTreeOpCC* tree) int CodeGenInterface::genSPtoFPdelta() const { assert(isFramePointerUsed()); + assert(compiler->compCalleeRegsPushed >= 2); - int delta = compiler->lvaOutgoingArgSpaceSize; + int delta = compiler->lvaOutgoingArgSpaceSize + (compiler->compCalleeRegsPushed << 3) - 8; assert(delta >= 0); return delta; @@ -4538,9 +4367,7 @@ int CodeGenInterface::genTotalFrameSize() const int CodeGenInterface::genCallerSPtoFPdelta() const { assert(isFramePointerUsed()); - int callerSPtoFPdelta; - - callerSPtoFPdelta = genCallerSPtoInitialSPdelta() + genSPtoFPdelta(); + int callerSPtoFPdelta = genCallerSPtoInitialSPdelta() + genSPtoFPdelta(); assert(callerSPtoFPdelta <= 0); return callerSPtoFPdelta; @@ -4553,9 +4380,7 @@ int CodeGenInterface::genCallerSPtoFPdelta() const int CodeGenInterface::genCallerSPtoInitialSPdelta() const { - int callerSPtoSPdelta = 0; - - callerSPtoSPdelta -= genTotalFrameSize(); + int callerSPtoSPdelta = -genTotalFrameSize(); assert(callerSPtoSPdelta <= 0); return callerSPtoSPdelta; @@ -5248,6 +5073,12 @@ void CodeGen::genSetGSSecurityCookie(regNumber initReg, bool* pInitRegZeroed) return; } + if (compiler->opts.IsOSR() && compiler->info.compPatchpointInfo->HasSecurityCookie()) + { + // Security cookie is on original frame and was initialized there. + return; + } + if (compiler->gsGlobalSecurityCookieAddr == nullptr) { noway_assert(compiler->gsGlobalSecurityCookieVal != 0); @@ -7851,7 +7682,7 @@ inline void CodeGen::genJumpToThrowHlpBlk_la( callType = emitter::EC_INDIR_R; callTarget = REG_DEFAULT_HELPER_CALL_TARGET; - // ssize_t imm = (4 + 1 + 1) << 2;// 4=li, 1=ld, 1=jirl. + // ssize_t imm = (4 + 1 + 1) << 2;// 4=li, 1=load, 1=jirl. // instGen_Set_Reg_To_Imm(EA_PTR_DSP_RELOC, callTarget, (ssize_t)pAddr); // emit->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, callTarget, callTarget, 0); @@ -7959,7 +7790,66 @@ void CodeGen::genProfilingLeaveCallback(unsigned helper /*= CORINFO_HELP_PROF_FC /*----------------------------------------------------------------------------- * - * Push/Pop any callee-saved registers we have used + * Push/Pop any callee-saved registers we have used + * For most frames, generatint liking: + * addi.d sp, sp, -totalFrameSize + * fst.d f24,sp,off + * ... + * fst.d f31,sp,off+7*8 + * + * st.d s0,sp,off2 + * st.d s1,sp,off2+8 + * ... + * st.d s8,sp,off2+8*8 + * + * st.d ra,sp,off3 + * st.d fp,sp,off3+8 + * + * Notes: + * 1. FP is always saved, and the first store is FP, RA. + * 2. General-purpose registers are 8 bytes, floating-point registers are 8 bytes. + * 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. + * 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: + * + * | | + * |-----------------------| + * | 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) + * |-----------------------| + * | locals, temps, etc. | + * |-----------------------| + * | possible GS cookie | + * |-----------------------| + * | Saved FP | // 8 bytes + * |-----------------------| + * | Saved RA | // 8 bytes + * |-----------------------| + * |Callee saved registers | // not including FP/RA; multiple of 8 bytes + * |-----------------------| + * | Outgoing arg space | // multiple of 8 bytes; if required (i.e., #outsz != 0) + * |-----------------------| <---- Ambient SP + * | | | + * ~ | Stack grows ~ + * | | downward | + * V + * */ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroed) { @@ -7974,11 +7864,8 @@ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroe } #endif - // On LA we push the FP (frame-pointer) here along with all other callee saved registers - if (isFramePointerUsed()) - { - rsPushRegs |= RBM_FPBASE; - } + // We always use the FP (frame-pointer). + assert(isFramePointerUsed()); // // It may be possible to skip pushing/popping ra for leaf methods. However, such optimization would require @@ -8000,122 +7887,22 @@ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroe // is not worth it. // - rsPushRegs |= RBM_RA; // We must save the return address (in the RA register). - regSet.rsMaskCalleeSaved = rsPushRegs; - regMaskTP maskSaveRegsFloat = rsPushRegs & RBM_ALLFLOAT; - regMaskTP maskSaveRegsInt = rsPushRegs & ~maskSaveRegsFloat; + regSet.rsMaskCalleeSaved = rsPushRegs | RBM_FPBASE | RBM_RA; #ifdef DEBUG - if (compiler->compCalleeRegsPushed != genCountBits(rsPushRegs)) + if (compiler->compCalleeRegsPushed != genCountBits(regSet.rsMaskCalleeSaved)) { printf("Error: unexpected number of callee-saved registers to push. Expected: %d. Got: %d ", - compiler->compCalleeRegsPushed, genCountBits(rsPushRegs)); - dspRegMask(rsPushRegs); + compiler->compCalleeRegsPushed, genCountBits(rsPushRegs | RBM_FPBASE | RBM_RA)); + dspRegMask(rsPushRegs | RBM_FPBASE | RBM_RA); printf("\n"); - assert(compiler->compCalleeRegsPushed == genCountBits(rsPushRegs)); + assert(compiler->compCalleeRegsPushed == genCountBits(rsPushRegs | RBM_FPBASE | RBM_RA)); } -#endif // DEBUG - - // See the document "LOONGARCH64 JIT Frame Layout" and/or "LOONGARCH64 Exception Data" for more details or - // requirements and - // options. Case numbers in comments here refer to this document. See also Compiler::lvaAssignFrameOffsets() - // for pictures of the general frame layouts, and CodeGen::genFuncletProlog() implementations (per architecture) - // for pictures of the funclet frame layouts. - // - // For most frames, generate, e.g.: - // sdc1 f31, off+7*8(sp) - // ... - // sdc1 f24, off(sp) - // - // sd s7, off2+7*8(sp) - // ... - // sd s1, off2+8(sp) - // sd s0, off2(sp) - // - // sd fp, 0(sp) - // sd ra, 8(sp) - // - // Notes: - // 1. FP is always saved, and the first store is FP, RA. - // 2. General-purpose registers are 8 bytes, floating-point registers are 8 bytes, but SIMD/FP registers 16 bytes. - // TODO-LOONGARCH64: supporting SIMD feature ! - // 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. - // 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(). - // - // - // Frames with FP, RA saved at bottom of frame (above outgoing argument space): - // - // | | - // |-----------------------| - // | incoming arguments | - // +=======================+ <---- Caller's SP - // | Arguments Or | // if needed. - // | Varargs regs space | // Only for varargs functions; (varargs not implemented for LoongArch64) - // |-----------------------| - // |Callee saved registers | // not including FP/RA; multiple of 8 bytes - // |-----------------------| - // | PSP slot | // 8 bytes (omitted in NativeAOT ABI) - // |-----------------------| - // | locals, temps, etc. | - // |-----------------------| - // | possible GS cookie | - // |-----------------------| - // | Saved RA | // 8 bytes - // |-----------------------| - // | Saved FP | // 8 bytes - // |-----------------------| - // | Outgoing arg space | // multiple of 8 bytes; if required (i.e., #outsz != 0) - // |-----------------------| <---- Ambient SP - // | | | - // ~ | Stack grows ~ - // | | downward | - // V - // - // - // Frames with FP, RA saved at top of frame (note: above all callee-saved regs): - // - // | | - // |-----------------------| - // | incoming arguments | - // +=======================+ <---- Caller's SP - // | Arguments Or | // if needed. - // | Varargs regs space | // Only for varargs functions; (varargs not implemented for LoongArch64) - // |-----------------------| - // | Saved RA | // 8 bytes - // |-----------------------| - // | Saved FP | // 8 bytes - // |-----------------------| - // |Callee saved registers | // not including FP/RA; multiple of 8 bytes - // |-----------------------| - // | PSP slot | // 8 bytes (omitted in NativeAOT ABI) - // |-----------------------| - // | locals, temps, etc. | - // |-----------------------| - // | possible GS cookie | - // |-----------------------| - // | Outgoing arg space | // multiple of 8 bytes; if required (i.e., #outsz != 0) - // |-----------------------| <---- Ambient SP - // | | | - // ~ | Stack grows ~ - // | | downward | - // V - // - - int totalFrameSize = genTotalFrameSize(); - int offset; // This will be the starting place for saving the callee-saved registers, in increasing order. - -#ifdef DEBUG if (verbose) { + regMaskTP maskSaveRegsFloat = rsPushRegs & RBM_ALLFLOAT; + regMaskTP maskSaveRegsInt = rsPushRegs & ~maskSaveRegsFloat; printf("Save float regs: "); dspRegMask(maskSaveRegsFloat); printf("\n"); @@ -8129,100 +7916,80 @@ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroe // 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. + // The amount to add from SP before starting to store the callee-saved registers. int calleeSaveSPDelta = 0; - // By default, we'll establish the frame pointer chain. (Note that currently frames without FP are NYI.) - bool establishFramePointer = true; + // 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. + // - // If we do establish the frame pointer, what is the amount we add to SP to do so? - unsigned offsetSpToSavedFp = 0; + // This will be the starting place for saving the callee-saved registers, in increasing order. + int offset = compiler->lvaOutgoingArgSpaceSize; - if (isFramePointerUsed()) + int totalFrameSize = genTotalFrameSize(); + // The (totalFrameSize <= 2040) condition ensures the offsets of st.d/ld.d. + if (totalFrameSize <= 2040) { - // We need to save both FP and RA. - - assert((maskSaveRegsInt & RBM_FP) != 0); - assert((maskSaveRegsInt & RBM_RA) != 0); + GetEmitter()->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, -totalFrameSize); + compiler->unwindAllocStack(totalFrameSize); - // 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. + // Case #1. // - // After the frame is allocated, the frame pointer is established, pointing at the saved frame pointer to - // create a frame pointer chain. + // 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. - if (totalFrameSize < 2048) - { - GetEmitter()->emitIns_R_R_I(INS_addi_d, 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); - // Case #1. - // - // Generate: - // daddiu sp, sp, -framesz - // sd fp, outsz(sp) - // sd ra, outsz+8(sp) - // - // The (totalFrameSize <= 2047) condition ensures the offsets of sd/ld. - // - // After saving callee-saved registers, we establish the frame pointer with: - // daddiu fp, sp, offset-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; - - offsetSpToSavedFp = compiler->lvaOutgoingArgSpaceSize; - - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_FP, REG_SPBASE, offsetSpToSavedFp); - compiler->unwindSaveReg(REG_FP, offsetSpToSavedFp); + frameType = 1; + } + else + { + JITDUMP("Frame type 2. #outsz=%d; #framesz=%d; LclFrameSize=%d\n", unsigned(compiler->lvaOutgoingArgSpaceSize), + totalFrameSize, compiler->compLclFrameSize); - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_RA, REG_SPBASE, offsetSpToSavedFp + 8); - compiler->unwindSaveReg(REG_RA, offsetSpToSavedFp + 8); + frameType = 2; - maskSaveRegsInt &= ~(RBM_FP | RBM_RA); // We've already saved FP/RA + if ((offset + (compiler->compCalleeRegsPushed << 3)) >= 2040) + { + offset = totalFrameSize - compiler->lvaOutgoingArgSpaceSize; + calleeSaveSPDelta = AlignUp((UINT)offset, STACK_ALIGN); + offset = calleeSaveSPDelta - offset; - offset = compiler->compLclFrameSize + 2 * REGSIZE_BYTES; // FP/RA + genStackPointerAdjustment(-calleeSaveSPDelta, initReg, pInitRegZeroed, /* reportUnwindData */ true); } else { - JITDUMP("Frame type 2. #outsz=%d; #framesz=%d; LclFrameSize=%d\n", - unsigned(compiler->lvaOutgoingArgSpaceSize), totalFrameSize, compiler->compLclFrameSize); - - frameType = 2; - - maskSaveRegsInt &= ~(RBM_FP | RBM_RA); // We've already saved FP/RA - - offset = totalFrameSize - compiler->compLclFrameSize - 2 * REGSIZE_BYTES; - calleeSaveSPDelta = AlignUp((UINT)offset, STACK_ALIGN); - offset = calleeSaveSPDelta - offset; + genStackPointerAdjustment(-totalFrameSize, initReg, pInitRegZeroed, /* reportUnwindData */ true); } } - else - { - // No frame pointer (no chaining). - assert((maskSaveRegsInt & RBM_FP) == 0); - assert((maskSaveRegsInt & RBM_RA) != 0); - // Note that there is no pre-indexed save_lrpair unwind code variant, so we can't allocate the frame using - // 'sd' if we only have one callee-saved register plus RA to save. + JITDUMP(" offset=%d, calleeSaveSPDelta=%d\n", offset, calleeSaveSPDelta); + genSaveCalleeSavedRegistersHelp(rsPushRegs, offset, 0); + offset += (int)(genCountBits(rsPushRegs) << 3); - NYI("Frame without frame pointer"); - offset = 0; - } + GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_RA, REG_SPBASE, offset); + compiler->unwindSaveReg(REG_RA, offset); - assert(frameType != 0); + GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_FP, REG_SPBASE, offset + 8); + compiler->unwindSaveReg(REG_FP, offset + 8); - JITDUMP(" offset=%d, calleeSaveSPDelta=%d\n", offset, calleeSaveSPDelta); - genSaveCalleeSavedRegistersHelp(maskSaveRegsInt | maskSaveRegsFloat, offset, -calleeSaveSPDelta); + JITDUMP(" offsetSpToSavedFp=%d\n", offset + 8); + genEstablishFramePointer(offset + 8, /* 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 @@ -8236,63 +8003,16 @@ void CodeGen::genPushCalleeSavedRegisters(regNumber initReg, bool* pInitRegZeroe #ifdef DEBUG if (compiler->opts.disAsm) { + assert(frameType != 0); printf("DEBUG: LOONGARCH64, frameType:%d\n\n", frameType); } #endif - if (frameType == 1) - { - // offsetSpToSavedFp = genSPtoFPdelta(); - } - else if (frameType == 2) - { - if (compiler->lvaOutgoingArgSpaceSize >= 2040) - { - offset = totalFrameSize - calleeSaveSPDelta - compiler->lvaOutgoingArgSpaceSize; - calleeSaveSPDelta = AlignUp((UINT)offset, STACK_ALIGN); - offset = calleeSaveSPDelta - offset; - genStackPointerAdjustment(-calleeSaveSPDelta, initReg, pInitRegZeroed, /* reportUnwindData */ true); - - offsetSpToSavedFp = offset; - - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_FP, REG_SPBASE, offset); - compiler->unwindSaveReg(REG_FP, offset); - - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_RA, REG_SPBASE, offset + 8); - compiler->unwindSaveReg(REG_RA, offset + 8); - - genEstablishFramePointer(offset, /* reportUnwindData */ true); - - calleeSaveSPDelta = compiler->lvaOutgoingArgSpaceSize & ~0xf; - genStackPointerAdjustment(-calleeSaveSPDelta, initReg, pInitRegZeroed, /* reportUnwindData */ true); - } - else - { - calleeSaveSPDelta = totalFrameSize - calleeSaveSPDelta; - genStackPointerAdjustment(-calleeSaveSPDelta, initReg, pInitRegZeroed, /* reportUnwindData */ true); - - offset = compiler->lvaOutgoingArgSpaceSize; - - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_FP, REG_SPBASE, offset); - compiler->unwindSaveReg(REG_FP, offset); - - GetEmitter()->emitIns_R_R_I(INS_st_d, EA_PTRSIZE, REG_RA, REG_SPBASE, offset + 8); - compiler->unwindSaveReg(REG_RA, offset + 8); - - genEstablishFramePointer(offset, /* reportUnwindData */ true); - } - - establishFramePointer = false; - } - else - { - unreached(); - } - - if (establishFramePointer) + if (calleeSaveSPDelta != 0) { - JITDUMP(" offsetSpToSavedFp=%d\n", offsetSpToSavedFp); - genEstablishFramePointer(offsetSpToSavedFp, /* reportUnwindData */ true); + assert(frameType == 2); + calleeSaveSPDelta = totalFrameSize - calleeSaveSPDelta; + genStackPointerAdjustment(-calleeSaveSPDelta, initReg, pInitRegZeroed, /* reportUnwindData */ true); } } @@ -8300,147 +8020,108 @@ void CodeGen::genPopCalleeSavedRegisters(bool jmpEpilog) { assert(compiler->compGeneratingEpilog); - regMaskTP rsRestoreRegs = regSet.rsGetModifiedRegsMask() & RBM_CALLEE_SAVED; + regMaskTP regsToRestoreMask = regSet.rsGetModifiedRegsMask() & RBM_CALLEE_SAVED; - if (isFramePointerUsed()) - { - rsRestoreRegs |= RBM_FPBASE; - } - - rsRestoreRegs |= RBM_RA; // We must save/restore the return address. + assert(isFramePointerUsed()); - regMaskTP regsToRestoreMask = rsRestoreRegs; + // 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) + { + JITDUMP("Frame type 1. #outsz=%d; #framesz=%d; localloc? %s\n", unsigned(compiler->lvaOutgoingArgSpaceSize), + totalFrameSize, dspBool(compiler->compLocallocUsed)); - int calleeSaveSPOffset = 0; // This will be the starting place for restoring - // the callee-saved registers, in decreasing order. - int frameType = 0; // An indicator of what type of frame we are popping. - int calleeSaveSPDelta = 0; // Amount to add to SP after callee-saved registers have been restored. + if (compiler->compLocallocUsed) + { + int SPtoFPdelta = (compiler->compCalleeRegsPushed << 3) - 8 + compiler->lvaOutgoingArgSpaceSize; - if (isFramePointerUsed()) + // 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; + } + else { - if (totalFrameSize <= 2047) + 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) { + calleeSaveSPOffset = compiler->lvaOutgoingArgSpaceSize & -16; if (compiler->compLocallocUsed) { - int SPtoFPdelta = genSPtoFPdelta(); + 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); } - - JITDUMP("Frame type 1(save FP/RA at bottom). #outsz=%d; #framesz=%d; localloc? %s\n", - unsigned(compiler->lvaOutgoingArgSpaceSize), totalFrameSize, dspBool(compiler->compLocallocUsed)); - - frameType = 1; - - regsToRestoreMask &= ~(RBM_FP | RBM_RA); // We'll restore FP/RA at the end. - - calleeSaveSPOffset = compiler->compLclFrameSize + 2 * REGSIZE_BYTES; + else + { + genStackPointerAdjustment(calleeSaveSPOffset, REG_RA, nullptr, /* reportUnwindData */ true); + } + remainingSPSize = totalFrameSize - calleeSaveSPOffset; + calleeSaveSPOffset = compiler->lvaOutgoingArgSpaceSize - calleeSaveSPOffset; } else { - JITDUMP("Frame type 2(save FP/RA at bottom). #outsz=%d; #framesz=%d; #calleeSaveRegsPushed:%d; " - "localloc? %s\n", - unsigned(compiler->lvaOutgoingArgSpaceSize), totalFrameSize, compiler->compCalleeRegsPushed, - dspBool(compiler->compLocallocUsed)); - - frameType = 2; - - int outSzAligned; - if (compiler->lvaOutgoingArgSpaceSize >= 2040) + if (compiler->compLocallocUsed) { - int offset = totalFrameSize - compiler->compLclFrameSize - 2 * REGSIZE_BYTES; - calleeSaveSPDelta = AlignUp((UINT)offset, STACK_ALIGN); - calleeSaveSPOffset = calleeSaveSPDelta - offset; - - int offset2 = totalFrameSize - calleeSaveSPDelta - compiler->lvaOutgoingArgSpaceSize; - calleeSaveSPDelta = AlignUp((UINT)offset2, STACK_ALIGN); - offset2 = calleeSaveSPDelta - offset2; - - if (compiler->compLocallocUsed) - { - // Restore sp from fp - GetEmitter()->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, -offset2); - compiler->unwindSetFrameReg(REG_FPBASE, offset2); - } - else - { - outSzAligned = compiler->lvaOutgoingArgSpaceSize & ~0xf; - genStackPointerAdjustment(outSzAligned, REG_R21, nullptr, /* reportUnwindData */ true); - } - - regsToRestoreMask &= ~(RBM_FP | RBM_RA); // We'll restore FP/RA at the end. - - GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_RA, REG_SPBASE, offset2 + 8); - compiler->unwindSaveReg(REG_RA, offset2 + 8); + int SPtoFPdelta = (compiler->compCalleeRegsPushed << 3) - 8 + compiler->lvaOutgoingArgSpaceSize; - GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_FP, REG_SPBASE, offset2); - compiler->unwindSaveReg(REG_FP, offset2); - - genStackPointerAdjustment(calleeSaveSPDelta, REG_R21, nullptr, /* reportUnwindData */ true); - - calleeSaveSPDelta = totalFrameSize - compiler->compLclFrameSize - 2 * REGSIZE_BYTES; - calleeSaveSPDelta = AlignUp((UINT)calleeSaveSPDelta, STACK_ALIGN); + // Restore sp from fp + GetEmitter()->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, -SPtoFPdelta); + compiler->unwindSetFrameReg(REG_FPBASE, SPtoFPdelta); } - else - { - int offset2 = compiler->lvaOutgoingArgSpaceSize; - if (compiler->compLocallocUsed) - { - // Restore sp from fp - GetEmitter()->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_FPBASE, -offset2); - compiler->unwindSetFrameReg(REG_FPBASE, offset2); - } - - regsToRestoreMask &= ~(RBM_FP | RBM_RA); // We'll restore FP/RA at the end. + calleeSaveSPOffset = compiler->lvaOutgoingArgSpaceSize; + remainingSPSize = totalFrameSize; + } + } - GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_RA, REG_SPBASE, offset2 + 8); - compiler->unwindSaveReg(REG_RA, offset2 + 8); + JITDUMP(" calleeSaveSPOffset=%d\n", calleeSaveSPOffset); + genRestoreCalleeSavedRegistersHelp(regsToRestoreMask, calleeSaveSPOffset, 0); + calleeSaveSPOffset += (compiler->compCalleeRegsPushed - 2) << 3; - GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_FP, REG_SPBASE, offset2); - compiler->unwindSaveReg(REG_FP, offset2); + GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_RA, REG_SPBASE, calleeSaveSPOffset); + compiler->unwindSaveReg(REG_RA, calleeSaveSPOffset); - calleeSaveSPOffset = totalFrameSize - compiler->compLclFrameSize - 2 * REGSIZE_BYTES; - calleeSaveSPDelta = AlignUp((UINT)calleeSaveSPOffset, STACK_ALIGN); - calleeSaveSPOffset = calleeSaveSPDelta - calleeSaveSPOffset; + GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_FP, REG_SPBASE, calleeSaveSPOffset + 8); + compiler->unwindSaveReg(REG_FP, calleeSaveSPOffset + 8); - genStackPointerAdjustment(totalFrameSize - calleeSaveSPDelta, REG_R21, nullptr, - /* reportUnwindData */ true); - } - } + if (emitter::isValidUimm11(remainingSPSize)) + { + GetEmitter()->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, remainingSPSize); } else { - // No frame pointer (no chaining). - NYI("Frame without frame pointer"); - calleeSaveSPOffset = 0; + 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); } + compiler->unwindAllocStack(remainingSPSize); - JITDUMP(" calleeSaveSPOffset=%d, calleeSaveSPDelta=%d\n", calleeSaveSPOffset, calleeSaveSPDelta); - genRestoreCalleeSavedRegistersHelp(regsToRestoreMask, calleeSaveSPOffset, calleeSaveSPDelta); - - if (frameType == 1) + // For OSR, we must also adjust the SP to remove the Tier0 frame. + if (compiler->opts.IsOSR()) { - calleeSaveSPOffset = compiler->lvaOutgoingArgSpaceSize; - - GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_RA, REG_SPBASE, calleeSaveSPOffset + 8); - compiler->unwindSaveReg(REG_RA, calleeSaveSPOffset + 8); + const int tier0FrameSize = compiler->info.compPatchpointInfo->TotalFrameSize(); + JITDUMP("Extra SP adjust for OSR to pop off Tier0 frame: %d bytes\n", tier0FrameSize); - GetEmitter()->emitIns_R_R_I(INS_ld_d, EA_PTRSIZE, REG_FP, REG_SPBASE, calleeSaveSPOffset); - compiler->unwindSaveReg(REG_FP, calleeSaveSPOffset); - - GetEmitter()->emitIns_R_R_I(INS_addi_d, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, totalFrameSize); - compiler->unwindAllocStack(totalFrameSize); - } - else if (frameType == 2) - { - // had done. - } - else - { - unreached(); + if (emitter::isValidUimm11(tier0FrameSize)) + { + GetEmitter()->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); + } + compiler->unwindAllocStack(tier0FrameSize); } } diff --git a/src/coreclr/jit/codegenriscv64.cpp b/src/coreclr/jit/codegenriscv64.cpp index 79ac3549c32841..e85a7336ccd014 100644 --- a/src/coreclr/jit/codegenriscv64.cpp +++ b/src/coreclr/jit/codegenriscv64.cpp @@ -76,7 +76,7 @@ bool CodeGen::genInstrWithConstant(instruction ins, // first we load the immediate into tmpReg assert(!EA_IS_RELOC(size)); - GetEmitter()->emitIns_I_la(size, tmpReg, imm); + GetEmitter()->emitLoadImmediate(size, tmpReg, imm); regSet.verifyRegUsed(tmpReg); // when we are in an unwind code region @@ -1230,7 +1230,7 @@ void CodeGen::instGen_Set_Reg_To_Imm(emitAttr size, } else { - emit->emitIns_I_la(size, reg, imm); + emit->emitLoadImmediate(size, reg, imm); } regSet.verifyRegUsed(reg); @@ -1308,7 +1308,25 @@ void CodeGen::genSetRegToConst(regNumber targetReg, var_types targetType, GenTre // Produce code for a GT_INC_SATURATE node. void CodeGen::genCodeForIncSaturate(GenTree* tree) { - NYI_RISCV64("genCodeForIncSaturate-----unimplemented/unused on RISCV64 yet----"); + regNumber targetReg = tree->GetRegNum(); + + // The arithmetic node must be sitting in a register (since it's not contained) + assert(!tree->isContained()); + // The dst can only be a register. + assert(targetReg != REG_NA); + + GenTree* operand = tree->gtGetOp1(); + assert(!operand->isContained()); + // The src must be a register. + regNumber operandReg = genConsumeReg(operand); + emitAttr attr = emitActualTypeSize(tree); + + GetEmitter()->emitIns_R_R_I(INS_addi, attr, targetReg, operandReg, 1); + // bne targetReg, zero, 2 * 4 + GetEmitter()->emitIns_R_R_I(INS_bne, attr, targetReg, REG_R0, 8); + GetEmitter()->emitIns_R_R_I(INS_xori, attr, targetReg, targetReg, -1); + + genProduceReg(tree); } // Generate code to get the high N bits of a N*N=2N bit multiplication result @@ -1556,7 +1574,7 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* lclNode) else if (data->IsIntegralConst()) { ssize_t imm = data->AsIntConCommon()->IconValue(); - emit->emitIns_I_la(EA_PTRSIZE, rsGetRsvdReg(), imm); + emit->emitLoadImmediate(EA_PTRSIZE, rsGetRsvdReg(), imm); dataReg = rsGetRsvdReg(); } else @@ -1792,7 +1810,7 @@ void CodeGen::genLclHeap(GenTree* tree) } else { - emit->emitIns_I_la(EA_PTRSIZE, rsGetRsvdReg(), amount); + emit->emitLoadImmediate(EA_PTRSIZE, rsGetRsvdReg(), amount); emit->emitIns_R_R_R(INS_sub, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, rsGetRsvdReg()); } @@ -2077,7 +2095,7 @@ void CodeGen::genCodeForDivMod(GenTreeOp* tree) { ssize_t intConst = (int)(divisorOp->AsIntCon()->gtIconVal); divisorReg = rsGetRsvdReg(); - emit->emitIns_I_la(EA_PTRSIZE, divisorReg, intConst); + emit->emitLoadImmediate(EA_PTRSIZE, divisorReg, intConst); } // Only for commutative operations do we check src1 and allow it to be a contained immediate else if (tree->OperIsCommutative()) @@ -2091,7 +2109,7 @@ void CodeGen::genCodeForDivMod(GenTreeOp* tree) assert(!divisorOp->isContainedIntOrIImmed()); ssize_t intConst = (int)(src1->AsIntCon()->gtIconVal); Reg1 = rsGetRsvdReg(); - emit->emitIns_I_la(EA_PTRSIZE, Reg1, intConst); + emit->emitLoadImmediate(EA_PTRSIZE, Reg1, intConst); } } else @@ -2965,7 +2983,7 @@ void CodeGen::genCodeForReturnTrap(GenTreeOp* tree) else { // TODO-RISCV64: maybe optimize further. - GetEmitter()->emitIns_I_la(EA_PTRSIZE, callTarget, (ssize_t)pAddr); + GetEmitter()->emitLoadImmediate(EA_PTRSIZE, callTarget, (ssize_t)pAddr); GetEmitter()->emitIns_R_R_I(INS_ld, EA_PTRSIZE, callTarget, callTarget, 0); } regSet.verifyRegUsed(callTarget); @@ -3507,7 +3525,7 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) } else { - emit->emitIns_I_la(EA_PTRSIZE, REG_RA, imm); + emit->emitLoadImmediate(EA_PTRSIZE, REG_RA, imm); emit->emitIns_R_R_R(IsUnsigned ? INS_sltu : INS_slt, EA_PTRSIZE, targetReg, regOp1, REG_RA); } } @@ -3523,7 +3541,7 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) } else { - emit->emitIns_I_la(EA_PTRSIZE, REG_RA, imm + 1); + emit->emitLoadImmediate(EA_PTRSIZE, REG_RA, imm + 1); emit->emitIns_R_R_R(IsUnsigned ? INS_sltu : INS_slt, EA_PTRSIZE, targetReg, regOp1, REG_RA); } } @@ -3541,7 +3559,7 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) } else { - emit->emitIns_I_la(EA_PTRSIZE, REG_RA, imm); + emit->emitLoadImmediate(EA_PTRSIZE, REG_RA, imm); emit->emitIns_R_R_R(IsUnsigned ? INS_sltu : INS_slt, EA_PTRSIZE, targetReg, REG_RA, regOp1); } } @@ -3557,7 +3575,7 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) } else { - emit->emitIns_I_la(EA_PTRSIZE, REG_RA, imm); + emit->emitLoadImmediate(EA_PTRSIZE, REG_RA, imm); emit->emitIns_R_R_R(IsUnsigned ? INS_sltu : INS_slt, EA_PTRSIZE, targetReg, regOp1, REG_RA); } emit->emitIns_R_R_I(INS_xori, EA_PTRSIZE, targetReg, targetReg, 1); @@ -3575,7 +3593,7 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) } else { - emit->emitIns_I_la(EA_PTRSIZE, REG_RA, imm); + emit->emitLoadImmediate(EA_PTRSIZE, REG_RA, imm); emit->emitIns_R_R_R(INS_xor, EA_PTRSIZE, targetReg, regOp1, REG_RA); emit->emitIns_R_R_R(INS_sltu, EA_PTRSIZE, targetReg, REG_R0, targetReg); } @@ -3593,7 +3611,7 @@ void CodeGen::genCodeForCompare(GenTreeOp* tree) } else { - emit->emitIns_I_la(EA_PTRSIZE, REG_RA, imm); + emit->emitLoadImmediate(EA_PTRSIZE, REG_RA, imm); emit->emitIns_R_R_R(INS_xor, EA_PTRSIZE, targetReg, regOp1, REG_RA); emit->emitIns_R_R_I(INS_sltiu, EA_PTRSIZE, targetReg, targetReg, 1); } @@ -3711,28 +3729,32 @@ void CodeGen::genCodeForJumpCompare(GenTreeOpCC* tree) switch (cmpSize) { case EA_4BYTE: + { + regNumber tmpRegOp1 = rsGetRsvdReg(); + assert(regOp1 != tmpRegOp1); if (cond.IsUnsigned()) { imm = static_cast(imm); - regNumber tmpRegOp1 = rsGetRsvdReg(); assert(regOp1 != tmpRegOp1); emit->emitIns_R_R_I(INS_slli, EA_8BYTE, tmpRegOp1, regOp1, 32); emit->emitIns_R_R_I(INS_srli, EA_8BYTE, tmpRegOp1, tmpRegOp1, 32); - regOp1 = tmpRegOp1; } else { imm = static_cast(imm); + emit->emitIns_R_R_I(INS_addiw, EA_8BYTE, tmpRegOp1, regOp1, 0); } + regOp1 = tmpRegOp1; break; + } case EA_8BYTE: break; default: unreached(); } - emit->emitIns_I_la(EA_PTRSIZE, REG_RA, imm); + emit->emitLoadImmediate(EA_PTRSIZE, REG_RA, imm); regs = (int)REG_RA << 5; } @@ -4280,7 +4302,7 @@ void CodeGen::genStackPointerConstantAdjustment(ssize_t spDelta, regNumber regTm } else { - GetEmitter()->emitIns_I_la(EA_PTRSIZE, regTmp, spDelta); + GetEmitter()->emitLoadImmediate(EA_PTRSIZE, regTmp, spDelta); GetEmitter()->emitIns_R_R_R(INS_add, EA_PTRSIZE, REG_SPBASE, REG_SPBASE, regTmp); } } @@ -4748,7 +4770,7 @@ void CodeGen::genSetGSSecurityCookie(regNumber initReg, bool* pInitRegZeroed) } else { - GetEmitter()->emitIns_I_la(EA_PTRSIZE, initReg, ((size_t)compiler->gsGlobalSecurityCookieAddr)); + GetEmitter()->emitLoadImmediate(EA_PTRSIZE, initReg, ((size_t)compiler->gsGlobalSecurityCookieAddr)); GetEmitter()->emitIns_R_R_I(INS_ld, EA_PTRSIZE, initReg, initReg, 0); } regSet.verifyRegUsed(initReg); @@ -5674,7 +5696,7 @@ void CodeGen::genCodeForIndexAddr(GenTreeIndexAddr* node) } else { - GetEmitter()->emitIns_I_la(EA_PTRSIZE, rsGetRsvdReg(), scale); + GetEmitter()->emitLoadImmediate(EA_PTRSIZE, rsGetRsvdReg(), scale); instruction ins; instruction ins2; @@ -6607,10 +6629,10 @@ void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, const GenIntCastDesc& d { const regNumber tempReg = rsGetRsvdReg(); assert(tempReg != reg); - GetEmitter()->emitIns_I_la(EA_8BYTE, tempReg, INT32_MAX); + GetEmitter()->emitLoadImmediate(EA_8BYTE, tempReg, INT32_MAX); genJumpToThrowHlpBlk_la(SCK_OVERFLOW, INS_blt, tempReg, nullptr, reg); - GetEmitter()->emitIns_I_la(EA_8BYTE, tempReg, INT32_MIN); + GetEmitter()->emitLoadImmediate(EA_8BYTE, tempReg, INT32_MIN); genJumpToThrowHlpBlk_la(SCK_OVERFLOW, INS_blt, reg, nullptr, tempReg); } break; @@ -6625,7 +6647,7 @@ void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, const GenIntCastDesc& d if (castMaxValue > 2047) { assert((castMaxValue == 32767) || (castMaxValue == 65535)); - GetEmitter()->emitIns_I_la(EA_ATTR(desc.CheckSrcSize()), rsGetRsvdReg(), castMaxValue + 1); + GetEmitter()->emitLoadImmediate(EA_ATTR(desc.CheckSrcSize()), rsGetRsvdReg(), castMaxValue + 1); ins = castMinValue == 0 ? INS_bgeu : INS_bge; genJumpToThrowHlpBlk_la(SCK_OVERFLOW, ins, reg, nullptr, rsGetRsvdReg()); } @@ -6646,7 +6668,7 @@ void CodeGen::genIntCastOverflowCheck(GenTreeCast* cast, const GenIntCastDesc& d } else { - GetEmitter()->emitIns_I_la(EA_8BYTE, rsGetRsvdReg(), castMinValue); + GetEmitter()->emitLoadImmediate(EA_8BYTE, rsGetRsvdReg(), castMinValue); GetEmitter()->emitIns_R_R_R(INS_slt, EA_ATTR(desc.CheckSrcSize()), rsGetRsvdReg(), reg, rsGetRsvdReg()); } @@ -6985,7 +7007,7 @@ void CodeGen::genLeaInstruction(GenTreeAddrMode* lea) regNumber tmpReg = lea->GetSingleTempReg(); // First load tmpReg with the large offset constant - emit->emitIns_I_la(EA_PTRSIZE, tmpReg, offset); + emit->emitLoadImmediate(EA_PTRSIZE, tmpReg, offset); // Then compute target reg from [memBase + tmpReg] emit->emitIns_R_R_R(INS_add, size, lea->GetRegNum(), memBase->GetRegNum(), tmpReg); @@ -7843,7 +7865,7 @@ void CodeGen::genFnPrologCalleeRegArgs() tmpReg = REG_RA; // Prepare tmpReg to possible future use - GetEmitter()->emitIns_I_la(EA_PTRSIZE, tmpReg, baseOffset); + 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); } @@ -7903,7 +7925,7 @@ void CodeGen::genFnPrologCalleeRegArgs() else { assert(!EA_IS_RELOC(size)); - GetEmitter()->emitIns_I_la(size, REG_SCRATCH, genTotalFrameSize()); + 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); } diff --git a/src/coreclr/jit/codegenxarch.cpp b/src/coreclr/jit/codegenxarch.cpp index 3d6291e7c11c36..6d7a973ad07520 100644 --- a/src/coreclr/jit/codegenxarch.cpp +++ b/src/coreclr/jit/codegenxarch.cpp @@ -3401,15 +3401,15 @@ void CodeGen::genCodeForCpBlkUnroll(GenTreeBlk* node) assert(srcOffset < (INT32_MAX - static_cast(size))); assert(dstOffset < (INT32_MAX - static_cast(size))); - if (size >= XMM_REGSIZE_BYTES) + // Get the largest SIMD register available if the size is large enough + unsigned regSize = compiler->roundDownSIMDSize(size); + + if ((size >= regSize) && (regSize > 0)) { regNumber tempReg = node->GetSingleTempReg(RBM_ALLFLOAT); instruction simdMov = simdUnalignedMovIns(); - // Get the largest SIMD register available if the size is large enough - unsigned regSize = compiler->roundDownSIMDSize(size); - auto emitSimdMovs = [&]() { if (srcLclNum != BAD_VAR_NUM) { diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index c0bfbb7a37203f..df7e672d955ea1 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -1329,7 +1329,7 @@ void Compiler::compStartup() emitter::emitInit(); // Static vars of ValueNumStore - ValueNumStore::InitValueNumStoreStatics(); + ValueNumStore::ValidateValueNumStoreStatics(); compDisplayStaticSizes(jitstdout); } @@ -2285,15 +2285,16 @@ void Compiler::compSetProcessor() // the overall JIT implementation, we currently require the entire set of ISAs to be // supported and disable AVX512 support otherwise. - if (instructionSetFlags.HasInstructionSet(InstructionSet_AVX512BW_VL) && - instructionSetFlags.HasInstructionSet(InstructionSet_AVX512CD_VL) && - instructionSetFlags.HasInstructionSet(InstructionSet_AVX512DQ_VL)) + if (instructionSetFlags.HasInstructionSet(InstructionSet_AVX512F)) { + assert(instructionSetFlags.HasInstructionSet(InstructionSet_AVX512F)); + assert(instructionSetFlags.HasInstructionSet(InstructionSet_AVX512F_VL)); assert(instructionSetFlags.HasInstructionSet(InstructionSet_AVX512BW)); + assert(instructionSetFlags.HasInstructionSet(InstructionSet_AVX512BW_VL)); assert(instructionSetFlags.HasInstructionSet(InstructionSet_AVX512CD)); + assert(instructionSetFlags.HasInstructionSet(InstructionSet_AVX512CD_VL)); assert(instructionSetFlags.HasInstructionSet(InstructionSet_AVX512DQ)); - assert(instructionSetFlags.HasInstructionSet(InstructionSet_AVX512F)); - assert(instructionSetFlags.HasInstructionSet(InstructionSet_AVX512F_VL)); + assert(instructionSetFlags.HasInstructionSet(InstructionSet_AVX512DQ_VL)); instructionSetFlags.AddInstructionSet(InstructionSet_Vector512); @@ -2308,32 +2309,6 @@ void Compiler::compSetProcessor() preferredVectorByteLength = 256 / 8; } } - else - { - instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX512F); - instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX512F_VL); - instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX512BW); - instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX512BW_VL); - instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX512CD); - instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX512CD_VL); - instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX512DQ); - instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX512DQ_VL); - instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX512VBMI); - instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX512VBMI_VL); - -#ifdef TARGET_AMD64 - instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX512F_X64); - instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX512F_VL_X64); - instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX512BW_X64); - instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX512BW_VL_X64); - instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX512CD_X64); - instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX512CD_VL_X64); - instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX512DQ_X64); - instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX512DQ_VL_X64); - instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX512VBMI_X64); - instructionSetFlags.RemoveInstructionSet(InstructionSet_AVX512VBMI_VL_X64); -#endif // TARGET_AMD64 - } opts.preferredVectorByteLength = preferredVectorByteLength; #elif defined(TARGET_ARM64) @@ -5580,7 +5555,7 @@ void Compiler::generatePatchpointInfo() // const int totalFrameSize = codeGen->genTotalFrameSize() + TARGET_POINTER_SIZE; const int offsetAdjust = 0; -#elif defined(TARGET_ARM64) +#elif defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) // SP is not manipulated by calls so no frame size adjustment needed. // Local Offsets may need adjusting, if FP is at bottom of frame. // @@ -6830,8 +6805,8 @@ int Compiler::compCompileHelper(CORINFO_MODULE_HANDLE classPtr, { frameSizeUpdate = 8; } -#elif defined(TARGET_ARM64) - if ((totalFrameSize % 16) != 0) +#elif defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) + if ((totalFrameSize & 0xf) != 0) { frameSizeUpdate = 8; } diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index c363ad7d9c7eed..65379c6c8240fb 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -7128,9 +7128,10 @@ class Compiler void pickGDV(GenTreeCall* call, IL_OFFSET ilOffset, bool isInterface, - CORINFO_CLASS_HANDLE* classGuess, - CORINFO_METHOD_HANDLE* methodGuess, - unsigned* likelihood); + CORINFO_CLASS_HANDLE* classGuesses, + CORINFO_METHOD_HANDLE* methodGuesses, + int* candidatesCount, + unsigned* likelihoods); void considerGuardedDevirtualization(GenTreeCall* call, IL_OFFSET ilOffset, @@ -8653,7 +8654,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // Get the number of bytes in a System.Numeric.Vector for the current compilation. // Note - cannot be used for System.Runtime.Intrinsic - unsigned getVectorTByteLength() + uint32_t getVectorTByteLength() { // We need to report the ISA dependency to the VM so that scenarios // such as R2R work correctly for larger vector sizes, so we always @@ -8661,17 +8662,31 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX CLANG_FORMAT_COMMENT_ANCHOR; #if defined(TARGET_XARCH) - if (compExactlyDependsOn(InstructionSet_AVX2)) + // TODO-XArch: Add support for 512-bit Vector + assert(!compIsaSupportedDebugOnly(InstructionSet_VectorT512)); + + if (compExactlyDependsOn(InstructionSet_VectorT256)) { - // TODO-XArch-AVX512 : Return ZMM_REGSIZE_BYTES once Vector supports AVX512. + assert(!compIsaSupportedDebugOnly(InstructionSet_VectorT128)); return YMM_REGSIZE_BYTES; } - else + else if (compExactlyDependsOn(InstructionSet_VectorT128)) { return XMM_REGSIZE_BYTES; } + else + { + return 0; + } #elif defined(TARGET_ARM64) - return FP_REGSIZE_BYTES; + if (compExactlyDependsOn(InstructionSet_VectorT128)) + { + return FP_REGSIZE_BYTES; + } + else + { + return 0; + } #else assert(!"getVectorTByteLength() unimplemented on target arch"); unreached(); @@ -8690,23 +8705,33 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX uint32_t getMaxVectorByteLength() const { #if defined(FEATURE_HW_INTRINSICS) && defined(TARGET_XARCH) - if (compOpportunisticallyDependsOn(InstructionSet_AVX)) + if (compOpportunisticallyDependsOn(InstructionSet_AVX512F)) { - if (compOpportunisticallyDependsOn(InstructionSet_AVX512F)) - { - return ZMM_REGSIZE_BYTES; - } - else - { - return YMM_REGSIZE_BYTES; - } + return ZMM_REGSIZE_BYTES; } - else + else if (compOpportunisticallyDependsOn(InstructionSet_AVX)) + { + return YMM_REGSIZE_BYTES; + } + else if (compOpportunisticallyDependsOn(InstructionSet_SSE)) { return XMM_REGSIZE_BYTES; } + else + { + assert((JitConfig.EnableHWIntrinsic() == 0) || (JitConfig.EnableSSE() == 0)); + return 0; + } #elif defined(TARGET_ARM64) - return FP_REGSIZE_BYTES; + if (compOpportunisticallyDependsOn(InstructionSet_AdvSimd)) + { + return FP_REGSIZE_BYTES; + } + else + { + assert((JitConfig.EnableHWIntrinsic() == 0) || (JitConfig.EnableArm64AdvSimd() == 0)); + return 0; + } #else assert(!"getMaxVectorByteLength() unimplemented on target arch"); unreached(); diff --git a/src/coreclr/jit/compiler.hpp b/src/coreclr/jit/compiler.hpp index b22bc7c519b0c9..c79c5edbeea1b5 100644 --- a/src/coreclr/jit/compiler.hpp +++ b/src/coreclr/jit/compiler.hpp @@ -430,36 +430,34 @@ static BasicBlockVisit VisitSuccessorEHSuccessors(Compiler* comp, BasicBlock* bl } //------------------------------------------------------------------------------ -// VisitAllSuccsInternal: Internal helper function to visit all successors -// (including EH successors) of a block. +// VisitAllSuccs: Visit all successors (including EH successors) of this block. // // Arguments: // comp - Compiler instance -// block - The block // func - Callback // // Returns: // Whether or not the visiting was aborted. // template -static BasicBlockVisit VisitAllSuccsInternal(Compiler* comp, BasicBlock* block, TFunc func) +BasicBlockVisit BasicBlock::VisitAllSuccs(Compiler* comp, TFunc func) { - switch (block->bbJumpKind) + switch (bbJumpKind) { case BBJ_EHFILTERRET: - RETURN_ON_ABORT(func(block->bbJumpDest)); - RETURN_ON_ABORT(VisitEHSuccessors(comp, block, func)); - RETURN_ON_ABORT(VisitSuccessorEHSuccessors(comp, block, block->bbJumpDest, func)); + RETURN_ON_ABORT(func(bbJumpDest)); + RETURN_ON_ABORT(VisitEHSuccessors(comp, this, func)); + RETURN_ON_ABORT(VisitSuccessorEHSuccessors(comp, this, bbJumpDest, func)); break; case BBJ_EHFINALLYRET: { - EHblkDsc* ehDsc = comp->ehGetDsc(block->getHndIndex()); + EHblkDsc* ehDsc = comp->ehGetDsc(getHndIndex()); assert(ehDsc->HasFinallyHandler()); BasicBlock* begBlk; BasicBlock* endBlk; - comp->ehGetCallFinallyBlockRange(block->getHndIndex(), &begBlk, &endBlk); + comp->ehGetCallFinallyBlockRange(getHndIndex(), &begBlk, &endBlk); BasicBlock* finBeg = ehDsc->ebdHndBeg; @@ -475,7 +473,7 @@ static BasicBlockVisit VisitAllSuccsInternal(Compiler* comp, BasicBlock* block, RETURN_ON_ABORT(func(bcall->bbNext)); } - RETURN_ON_ABORT(VisitEHSuccessors(comp, block, func)); + RETURN_ON_ABORT(VisitEHSuccessors(comp, this, func)); for (BasicBlock* bcall = begBlk; bcall != endBlk; bcall = bcall->bbNext) { @@ -485,7 +483,7 @@ static BasicBlockVisit VisitAllSuccsInternal(Compiler* comp, BasicBlock* block, } assert(bcall->isBBCallAlwaysPair()); - RETURN_ON_ABORT(VisitSuccessorEHSuccessors(comp, block, bcall->bbNext, func)); + RETURN_ON_ABORT(VisitSuccessorEHSuccessors(comp, this, bcall->bbNext, func)); } break; @@ -494,61 +492,61 @@ static BasicBlockVisit VisitAllSuccsInternal(Compiler* comp, BasicBlock* block, case BBJ_CALLFINALLY: case BBJ_EHCATCHRET: case BBJ_LEAVE: - RETURN_ON_ABORT(func(block->bbJumpDest)); - RETURN_ON_ABORT(VisitEHSuccessors(comp, block, func)); - RETURN_ON_ABORT(VisitSuccessorEHSuccessors(comp, block, block->bbJumpDest, func)); + RETURN_ON_ABORT(func(bbJumpDest)); + RETURN_ON_ABORT(VisitEHSuccessors(comp, this, func)); + RETURN_ON_ABORT(VisitSuccessorEHSuccessors(comp, this, bbJumpDest, func)); break; case BBJ_ALWAYS: - RETURN_ON_ABORT(func(block->bbJumpDest)); + RETURN_ON_ABORT(func(bbJumpDest)); - // If "block" is a "leave helper" block (the empty BBJ_ALWAYS block + // If this is a "leave helper" block (the empty BBJ_ALWAYS block // that pairs with a preceding BBJ_CALLFINALLY block to implement a // "leave" IL instruction), then no exceptions can occur within it // and we skip its normal EH successors. - if (!block->isBBCallAlwaysPairTail()) + if (!isBBCallAlwaysPairTail()) { - RETURN_ON_ABORT(VisitEHSuccessors(comp, block, func)); + RETURN_ON_ABORT(VisitEHSuccessors(comp, this, func)); } - RETURN_ON_ABORT(VisitSuccessorEHSuccessors(comp, block, block->bbJumpDest, func)); + RETURN_ON_ABORT(VisitSuccessorEHSuccessors(comp, this, bbJumpDest, func)); break; case BBJ_NONE: - RETURN_ON_ABORT(func(block->bbNext)); - RETURN_ON_ABORT(VisitEHSuccessors(comp, block, func)); - RETURN_ON_ABORT(VisitSuccessorEHSuccessors(comp, block, block->bbNext, func)); + RETURN_ON_ABORT(func(bbNext)); + RETURN_ON_ABORT(VisitEHSuccessors(comp, this, func)); + RETURN_ON_ABORT(VisitSuccessorEHSuccessors(comp, this, bbNext, func)); break; case BBJ_COND: - RETURN_ON_ABORT(func(block->bbNext)); + RETURN_ON_ABORT(func(bbNext)); - if (block->bbJumpDest != block->bbNext) + if (bbJumpDest != bbNext) { - RETURN_ON_ABORT(func(block->bbJumpDest)); + RETURN_ON_ABORT(func(bbJumpDest)); } - RETURN_ON_ABORT(VisitEHSuccessors(comp, block, func)); - RETURN_ON_ABORT(VisitSuccessorEHSuccessors(comp, block, block->bbNext, func)); + RETURN_ON_ABORT(VisitEHSuccessors(comp, this, func)); + RETURN_ON_ABORT(VisitSuccessorEHSuccessors(comp, this, bbNext, func)); - if (block->bbJumpDest != block->bbNext) + if (bbJumpDest != bbNext) { - RETURN_ON_ABORT(VisitSuccessorEHSuccessors(comp, block, block->bbJumpDest, func)); + RETURN_ON_ABORT(VisitSuccessorEHSuccessors(comp, this, bbJumpDest, func)); } break; case BBJ_SWITCH: { - Compiler::SwitchUniqueSuccSet sd = comp->GetDescriptorForSwitch(block); + Compiler::SwitchUniqueSuccSet sd = comp->GetDescriptorForSwitch(this); for (unsigned i = 0; i < sd.numDistinctSuccs; i++) { RETURN_ON_ABORT(func(sd.nonDuplicates[i])); } - RETURN_ON_ABORT(VisitEHSuccessors(comp, block, func)); + RETURN_ON_ABORT(VisitEHSuccessors(comp, this, func)); for (unsigned i = 0; i < sd.numDistinctSuccs; i++) { - RETURN_ON_ABORT(VisitSuccessorEHSuccessors(comp, block, sd.nonDuplicates[i], func)); + RETURN_ON_ABORT(VisitSuccessorEHSuccessors(comp, this, sd.nonDuplicates[i], func)); } break; @@ -557,7 +555,7 @@ static BasicBlockVisit VisitAllSuccsInternal(Compiler* comp, BasicBlock* block, case BBJ_THROW: case BBJ_RETURN: case BBJ_EHFAULTRET: - RETURN_ON_ABORT(VisitEHSuccessors(comp, block, func)); + RETURN_ON_ABORT(VisitEHSuccessors(comp, this, func)); break; default: @@ -567,51 +565,6 @@ static BasicBlockVisit VisitAllSuccsInternal(Compiler* comp, BasicBlock* block, return BasicBlockVisit::Continue; } -//------------------------------------------------------------------------------ -// VisitAllSuccs: Visit all successors (including EH successors) of this block. -// -// Arguments: -// comp - Compiler instance -// func - Callback -// -// Returns: -// Whether or not the visiting was aborted. -// -template -BasicBlockVisit BasicBlock::VisitAllSuccs(Compiler* comp, TFunc func) -{ -#ifdef DEBUG - // Compare callback-based successors with old iterator based successors. - BasicBlock* succs[64]; - unsigned index = 0; - - VisitAllSuccsInternal(comp, this, [&succs, &index](BasicBlock* succ) { - if (index < ArrLen(succs)) - { - succs[index] = succ; - } - - index++; - return BasicBlockVisit::Continue; - }); - - unsigned index2 = 0; - for (BasicBlock* succ : GetAllSuccs(comp)) - { - if (index2 < ArrLen(succs)) - { - assert(succs[index2] == succ); - } - - index2++; - } - - assert(index == index2); -#endif - - return VisitAllSuccsInternal(comp, this, func); -} - #undef RETURN_ON_ABORT #if defined(FEATURE_EH_FUNCLETS) diff --git a/src/coreclr/jit/emit.h b/src/coreclr/jit/emit.h index 1d49eb69070061..9cab8e6fcea2ff 100644 --- a/src/coreclr/jit/emit.h +++ b/src/coreclr/jit/emit.h @@ -781,6 +781,9 @@ class emitter unsigned _idCallRegPtr : 1; // IL indirect calls: addr in reg unsigned _idCallAddr : 1; // IL indirect calls: can make a direct call to iiaAddr unsigned _idNoGC : 1; // Some helpers don't get recorded in GC tables +#if defined(TARGET_XARCH) + unsigned _idEvexbContext : 1; // does EVEX.b need to be set. +#endif // TARGET_XARCH #ifdef TARGET_ARM64 opSize _idOpSize : 3; // operand size: 0=1 , 1=2 , 2=4 , 3=8, 4=16 @@ -814,8 +817,8 @@ class emitter //////////////////////////////////////////////////////////////////////// // Space taken up to here: - // x86: 46 bits - // amd64: 46 bits + // x86: 47 bits + // amd64: 47 bits // arm: 48 bits // arm64: 50 bits // loongarch64: 46 bits @@ -830,8 +833,10 @@ class emitter #define ID_EXTRA_BITFIELD_BITS (16) #elif defined(TARGET_ARM64) #define ID_EXTRA_BITFIELD_BITS (18) -#elif defined(TARGET_XARCH) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) +#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) #define ID_EXTRA_BITFIELD_BITS (14) +#elif defined(TARGET_XARCH) +#define ID_EXTRA_BITFIELD_BITS (15) #else #error Unsupported or unset target architecture #endif @@ -866,8 +871,8 @@ class emitter //////////////////////////////////////////////////////////////////////// // Space taken up to here (with/without prev offset, assuming host==target): - // x86: 52/48 bits - // amd64: 53/48 bits + // x86: 53/49 bits + // amd64: 54/49 bits // arm: 54/50 bits // arm64: 57/52 bits // loongarch64: 53/48 bits @@ -1136,7 +1141,7 @@ class emitter void idCodeSize(unsigned sz) { // RISCV64's instrDesc is not always meaning only one instruction. - // e.g. the `emitter::emitIns_I_la` for emitting the immediates. + // e.g. the `emitter::emitLoadImmediate` for emitting the immediates. assert(sz <= 32); _idCodeSize = sz; } @@ -1529,6 +1534,19 @@ class emitter _idNoGC = val; } +#ifdef TARGET_XARCH + bool idIsEvexbContext() const + { + return _idEvexbContext != 0; + } + void idSetEvexbContext() + { + assert(_idEvexbContext == 0); + _idEvexbContext = 1; + assert(_idEvexbContext == 1); + } +#endif + #ifdef TARGET_ARMARCH bool idIsLclVar() const { @@ -3655,9 +3673,25 @@ inline unsigned emitter::emitGetInsCIargs(instrDesc* id) // emitAttr emitter::emitGetMemOpSize(instrDesc* id) const { + emitAttr defaultSize = id->idOpSize(); instruction ins = id->idIns(); + if (id->idIsEvexbContext()) + { + // should have the assumption that Evex.b now stands for the embedded broadcast context. + // reference: Section 2.7.5 in Intel 64 and ia-32 architectures software developer's manual volume 2. + ssize_t inputSize = GetInputSizeInBytes(id); + switch (inputSize) + { + case 4: + return EA_4BYTE; + case 8: + return EA_8BYTE; + default: + unreached(); + } + } switch (ins) { case INS_pextrb: diff --git a/src/coreclr/jit/emitriscv64.cpp b/src/coreclr/jit/emitriscv64.cpp index 40a9e7c4647f36..c4cf931d2186a5 100644 --- a/src/coreclr/jit/emitriscv64.cpp +++ b/src/coreclr/jit/emitriscv64.cpp @@ -1117,60 +1117,64 @@ void emitter::emitIns_J_cond_la(instruction ins, BasicBlock* dst, regNumber reg1 appendToCurIG(id); } -void emitter::emitIns_I_la(emitAttr size, regNumber reg, ssize_t imm) +/***************************************************************************** + * + * Emits load of 64-bit constant to register. + * + */ +void emitter::emitLoadImmediate(emitAttr size, regNumber reg, ssize_t imm) { + // In the worst case a sequence of 8 instructions will be used: + // LUI + ADDIW + SLLI + ADDI + SLLI + ADDI + SLLI + ADDI + // + // First 2 instructions (LUI + ADDIW) load up to 31 bit. And followed + // sequence of (SLLI + ADDI) is used for loading remaining part by batches + // of up to 11 bits. + // + // Note that LUI, ADDI/W use sign extension so that's why we have to work + // with 31 and 11 bit batches there. + assert(!EA_IS_RELOC(size)); assert(isGeneralRegister(reg)); - // TODO-CQ-RISCV: at least for imm=-2*1024*1024*1024 (and similar ones) code can be simplified to "lui rd, 0x80000" + if (isValidSimm12(imm)) + { + emitIns_R_R_I(INS_addi, size, reg, REG_R0, imm & 0xFFF); + return; + } + + // TODO-RISCV64: maybe optimized via emitDataConst(), check #86790 - if (0 == ((imm + 0x800) >> 31)) + UINT32 msb = BitOperations::BitScanReverse((uint64_t)imm); + UINT32 high31; + if (msb > 30) { - if (((imm + 0x800) >> 12) != 0) - { - emitIns_R_I(INS_lui, size, reg, ((imm + 0x800) >> 12)); - if ((imm & 0xFFF) != 0) - { - emitIns_R_R_I(size == EA_4BYTE ? INS_addiw : INS_addi, size, reg, reg, imm & 0xFFF); - } - } - else - { - emitIns_R_R_I(size == EA_4BYTE ? INS_addiw : INS_addi, size, reg, REG_R0, imm & 0xFFF); - } + high31 = (imm >> (msb - 30)) & 0x7FffFFff; } else { - UINT32 high = (imm >> 33) & 0x7fffffff; - regNumber highReg = reg; - if (((high + 0x800) >> 12) != 0) - { - emitIns_R_I(INS_lui, size, highReg, ((high + 0x800) >> 12)); - if ((high & 0xFFF) != 0) - { - emitIns_R_R_I(size == EA_4BYTE ? INS_addiw : INS_addi, size, highReg, highReg, high & 0xFFF); - } - } - else if ((high & 0xFFF) != 0) - { - emitIns_R_R_I(size == EA_4BYTE ? INS_addiw : INS_addi, size, highReg, REG_R0, high & 0xFFF); - } - else - { - highReg = REG_R0; - } - UINT64 low = imm & 0x1ffffffff; - if (highReg != REG_R0) - { - emitIns_R_R_I(size == EA_4BYTE ? INS_slliw : INS_slli, size, highReg, highReg, 11); - } - emitIns_R_R_I(size == EA_4BYTE ? INS_addiw : INS_addi, size, reg, highReg, (low >> 22) & 0x7FF); + high31 = imm & 0x7FffFFff; + } - emitIns_R_R_I(size == EA_4BYTE ? INS_slliw : INS_slli, size, reg, reg, 11); - emitIns_R_R_I(size == EA_4BYTE ? INS_addiw : INS_addi, size, reg, reg, (low >> 11) & 0x7FF); + // 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; - emitIns_R_R_I(size == EA_4BYTE ? INS_slliw : INS_slli, size, reg, reg, 11); - emitIns_R_R_I(size == EA_4BYTE ? INS_addiw : INS_addi, size, reg, reg, low & 0x7FF); + emitIns_R_I(INS_lui, size, reg, high19); + emitIns_R_R_I(INS_addiw, size, reg, reg, high31 & 0xFFF); + + // And load remaining part part by batches of 11 bits size. + INT32 remainingShift = msb - 30; + while (remainingShift > 0) + { + UINT32 shift = remainingShift >= 11 ? 11 : remainingShift % 11; + emitIns_R_R_I(INS_slli, size, reg, reg, shift); + + UINT32 mask = 0x7ff >> (11 - shift); + ssize_t low11 = (imm >> (remainingShift - shift)) & mask; + emitIns_R_R_I(INS_addi, size, reg, reg, low11); + remainingShift = remainingShift - shift; } } @@ -3771,8 +3775,8 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR else // large offset { // First load/store tmpReg with the large offset constant - emitIns_I_la(EA_PTRSIZE, tmpReg, - offset); // codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset); + emitLoadImmediate(EA_PTRSIZE, tmpReg, + offset); // codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset); // Then add the base register // rd = rd + base emitIns_R_R_R(INS_add, addType, tmpReg, tmpReg, memBase->GetRegNum()); @@ -3899,7 +3903,7 @@ void emitter::emitInsLoadStoreOp(instruction ins, emitAttr attr, regNumber dataR regNumber tmpReg = indir->GetSingleTempReg(); // First load/store tmpReg with the large offset constant - emitIns_I_la(EA_PTRSIZE, tmpReg, offset); + emitLoadImmediate(EA_PTRSIZE, tmpReg, offset); // codeGen->instGen_Set_Reg_To_Imm(EA_PTRSIZE, tmpReg, offset); // Then load/store dataReg from/to [memBase + tmpReg] @@ -4160,7 +4164,7 @@ regNumber emitter::emitInsTernary(instruction ins, emitAttr attr, GenTree* dst, } else { - emitIns_R_R_R(INS_mulhu, attr, codeGen->rsGetRsvdReg(), src1->GetRegNum(), src2->GetRegNum()); + emitIns_R_R_R(INS_mulh, attr, codeGen->rsGetRsvdReg(), src1->GetRegNum(), src2->GetRegNum()); } } } diff --git a/src/coreclr/jit/emitriscv64.h b/src/coreclr/jit/emitriscv64.h index f9eb23be2f8de8..a572ee9d2cf8c9 100644 --- a/src/coreclr/jit/emitriscv64.h +++ b/src/coreclr/jit/emitriscv64.h @@ -32,7 +32,8 @@ 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); + +void emitLoadImmediate(emitAttr attr, regNumber reg, ssize_t imm); /************************************************************************/ /* Private members that deal with target-dependent instr. descriptors */ diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index db096a21f09699..e1586dcf9ff1b9 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -1231,9 +1231,10 @@ bool emitter::TakesEvexPrefix(const instrDesc* id) const #define DEFAULT_BYTE_EVEX_PREFIX_MASK 0xFFFFFFFF00000000ULL #define LBIT_IN_BYTE_EVEX_PREFIX 0x0000002000000000ULL #define LPRIMEBIT_IN_BYTE_EVEX_PREFIX 0x0000004000000000ULL +#define EVEX_B_BIT 0x0000001000000000ULL //------------------------------------------------------------------------ -// AddEvexPrefix: Add default EVEX perfix with only LL' bits set. +// AddEvexPrefix: Add default EVEX prefix with only LL' bits set. // // Arguments: // ins -- processor instruction to check. @@ -1268,6 +1269,22 @@ emitter::code_t emitter::AddEvexPrefix(instruction ins, code_t code, emitAttr at return code; } +//------------------------------------------------------------------------ +// AddEvexPrefix: set Evex.b bit if EvexbContext is set in instruction descritor. +// +// Arguments: +// code -- opcode bits. +// +// Return Value: +// encoded code with Evex.b set if needed. +// +emitter::code_t emitter::AddEvexbBit(code_t code) +{ + assert(hasEvexPrefix(code)); + code |= EVEX_B_BIT; + return code; +} + // Returns true if this instruction requires a VEX prefix // All AVX instructions require a VEX prefix bool emitter::TakesVexPrefix(instruction ins) const @@ -6667,7 +6684,8 @@ void emitter::emitIns_R_S_I(instruction ins, emitAttr attr, regNumber reg1, int emitCurIGsize += sz; } -void emitter::emitIns_R_R_A(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, GenTreeIndir* indir) +void emitter::emitIns_R_R_A( + instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, GenTreeIndir* indir, insOpts instOptions) { assert(IsAvx512OrPriorInstruction(ins)); assert(IsThreeOperandAVXInstruction(ins)); @@ -6678,6 +6696,11 @@ void emitter::emitIns_R_R_A(instruction ins, emitAttr attr, regNumber reg1, regN id->idIns(ins); id->idReg1(reg1); id->idReg2(reg2); + if (instOptions == INS_OPTS_EVEX_b) + { + assert(UseEvexEncoding()); + id->idSetEvexbContext(); + } emitHandleMemOp(indir, id, (ins == INS_mulx) ? IF_RWR_RWR_ARD : emitInsModeFormat(ins, IF_RRD_RRD_ARD), ins); @@ -6778,8 +6801,13 @@ void emitter::emitIns_R_AR_R(instruction ins, emitCurIGsize += sz; } -void emitter::emitIns_R_R_C( - instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, CORINFO_FIELD_HANDLE fldHnd, int offs) +void emitter::emitIns_R_R_C(instruction ins, + emitAttr attr, + regNumber reg1, + regNumber reg2, + CORINFO_FIELD_HANDLE fldHnd, + int offs, + insOpts instOptions) { assert(IsAvx512OrPriorInstruction(ins)); assert(IsThreeOperandAVXInstruction(ins)); @@ -6797,6 +6825,11 @@ void emitter::emitIns_R_R_C( id->idReg1(reg1); id->idReg2(reg2); id->idAddr()->iiaFieldHnd = fldHnd; + if (instOptions == INS_OPTS_EVEX_b) + { + assert(UseEvexEncoding()); + id->idSetEvexbContext(); + } UNATIVE_OFFSET sz = emitInsSizeCV(id, insCodeRM(ins)); id->idCodeSize(sz); @@ -6829,7 +6862,8 @@ void emitter::emitIns_R_R_R(instruction ins, emitAttr attr, regNumber targetReg, emitCurIGsize += sz; } -void emitter::emitIns_R_R_S(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int varx, int offs) +void emitter::emitIns_R_R_S( + instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int varx, int offs, insOpts instOptions) { assert(IsAvx512OrPriorInstruction(ins)); assert(IsThreeOperandAVXInstruction(ins)); @@ -6842,6 +6876,11 @@ void emitter::emitIns_R_R_S(instruction ins, emitAttr attr, regNumber reg1, regN id->idReg2(reg2); id->idAddr()->iiaLclVar.initLclVarAddr(varx, offs); + if (instOptions == INS_OPTS_EVEX_b) + { + assert(UseEvexEncoding()); + id->idSetEvexbContext(); + } #ifdef DEBUG id->idDebugOnlyInfo()->idVarRefOffs = emitVarRefOffs; #endif @@ -8134,14 +8173,15 @@ void emitter::emitIns_SIMD_R_R_I(instruction ins, emitAttr attr, regNumber targe // indir -- The GenTreeIndir used for the memory address // void emitter::emitIns_SIMD_R_R_A( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, GenTreeIndir* indir) + instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, GenTreeIndir* indir, insOpts instOptions) { if (UseSimdEncoding()) { - emitIns_R_R_A(ins, attr, targetReg, op1Reg, indir); + emitIns_R_R_A(ins, attr, targetReg, op1Reg, indir, instOptions); } else { + assert(instOptions == INS_OPTS_NONE); emitIns_Mov(INS_movaps, attr, targetReg, op1Reg, /* canSkip */ true); emitIns_R_A(ins, attr, targetReg, indir); } @@ -8159,15 +8199,21 @@ void emitter::emitIns_SIMD_R_R_A( // fldHnd -- The CORINFO_FIELD_HANDLE used for the memory address // offs -- The offset added to the memory address from fldHnd // -void emitter::emitIns_SIMD_R_R_C( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, CORINFO_FIELD_HANDLE fldHnd, int offs) +void emitter::emitIns_SIMD_R_R_C(instruction ins, + emitAttr attr, + regNumber targetReg, + regNumber op1Reg, + CORINFO_FIELD_HANDLE fldHnd, + int offs, + insOpts instOptions) { if (UseSimdEncoding()) { - emitIns_R_R_C(ins, attr, targetReg, op1Reg, fldHnd, offs); + emitIns_R_R_C(ins, attr, targetReg, op1Reg, fldHnd, offs, instOptions); } else { + assert(instOptions == INS_OPTS_NONE); emitIns_Mov(INS_movaps, attr, targetReg, op1Reg, /* canSkip */ true); emitIns_R_C(ins, attr, targetReg, fldHnd, offs); } @@ -8222,14 +8268,15 @@ void emitter::emitIns_SIMD_R_R_R( // offs -- The offset added to the memory address from varx // void emitter::emitIns_SIMD_R_R_S( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, int varx, int offs) + instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, int varx, int offs, insOpts instOptions) { if (UseSimdEncoding()) { - emitIns_R_R_S(ins, attr, targetReg, op1Reg, varx, offs); + emitIns_R_R_S(ins, attr, targetReg, op1Reg, varx, offs, instOptions); } else { + assert(instOptions == INS_OPTS_NONE); emitIns_Mov(INS_movaps, attr, targetReg, op1Reg, /* canSkip */ true); emitIns_R_S(ins, attr, targetReg, varx, offs); } @@ -15717,7 +15764,7 @@ BYTE* emitter::emitOutputLJ(insGroup* ig, BYTE* dst, instrDesc* i) // Return Value: // size in bytes. // -ssize_t emitter::GetInputSizeInBytes(instrDesc* id) +ssize_t emitter::GetInputSizeInBytes(instrDesc* id) const { insFlags inputSize = static_cast((CodeGenInterface::instInfo[id->idIns()] & Input_Mask)); @@ -18809,6 +18856,7 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins case INS_pcmpgtq: case INS_psadbw: case INS_vdbpsadbw: + case INS_vpcmpgtq: case INS_vpermps: case INS_vpermpd: case INS_vpermpd_reg: @@ -19243,10 +19291,6 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins break; } - case INS_kmovb_msk: - case INS_kmovw_msk: - case INS_kmovd_msk: - case INS_kmovq_msk: case INS_kmovb_gpr: case INS_kmovw_gpr: case INS_kmovd_gpr: @@ -19257,6 +19301,16 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins break; } + case INS_kmovb_msk: + case INS_kmovw_msk: + case INS_kmovd_msk: + case INS_kmovq_msk: + { + result.insLatency += PERFSCORE_LATENCY_1C; + result.insThroughput = PERFSCORE_THROUGHPUT_1C; + break; + } + case INS_vpcmpb: case INS_vpcmpw: case INS_vpcmpd: @@ -19286,13 +19340,72 @@ emitter::insExecutionCharacteristics emitter::getInsExecutionCharacteristics(ins break; } + case INS_kandb: + case INS_kandd: + case INS_kandq: + case INS_kandw: + case INS_kandnb: + case INS_kandnd: + case INS_kandnq: + case INS_kandnw: + case INS_knotb: + case INS_knotd: + case INS_knotq: + case INS_knotw: + case INS_korb: + case INS_kord: + case INS_korq: + case INS_korw: + case INS_kxnorb: + case INS_kxnord: + case INS_kxnorq: + case INS_kxnorw: + case INS_kxorb: + case INS_kxord: + case INS_kxorq: + case INS_kxorw: + { + result.insLatency += PERFSCORE_LATENCY_1C; + result.insThroughput = PERFSCORE_THROUGHPUT_1C; + break; + } + case INS_kortestb: - case INS_kortestw: case INS_kortestd: case INS_kortestq: + case INS_kortestw: + case INS_ktestb: + case INS_ktestd: + case INS_ktestq: + case INS_ktestw: { + // Keep these in a separate group as there isn't a documented latency + // Similar instructions have a 1 cycle latency, however + result.insLatency += PERFSCORE_LATENCY_1C; result.insThroughput = PERFSCORE_THROUGHPUT_1C; + + break; + } + + case INS_kaddb: + case INS_kaddd: + case INS_kaddq: + case INS_kaddw: + case INS_kshiftlb: + case INS_kshiftld: + case INS_kshiftlq: + case INS_kshiftlw: + case INS_kshiftrb: + case INS_kshiftrd: + case INS_kshiftrq: + case INS_kshiftrw: + case INS_kunpckbw: + case INS_kunpckdq: + case INS_kunpckwd: + { + result.insLatency += PERFSCORE_LATENCY_4C; + result.insThroughput = PERFSCORE_THROUGHPUT_1C; break; } diff --git a/src/coreclr/jit/emitxarch.h b/src/coreclr/jit/emitxarch.h index d70f2b6d92a409..082686fda18439 100644 --- a/src/coreclr/jit/emitxarch.h +++ b/src/coreclr/jit/emitxarch.h @@ -294,6 +294,7 @@ bool hasEvexPrefix(code_t code) return (code & EVEX_PREFIX_MASK) == EVEX_PREFIX_CODE; } code_t AddEvexPrefix(instruction ins, code_t code, emitAttr attr); +code_t AddEvexbBit(code_t code); //------------------------------------------------------------------------ // AddSimdPrefixIfNeeded: Add the correct SIMD prefix if required. @@ -314,6 +315,10 @@ code_t AddSimdPrefixIfNeeded(const instrDesc* id, code_t code, emitAttr size) if (TakesEvexPrefix(id)) { code = AddEvexPrefix(ins, code, size); + if (id->idIsEvexbContext()) + { + code = AddEvexbBit(code); + } } else if (TakesVexPrefix(ins)) { @@ -385,7 +390,7 @@ bool codeEvexMigrationCheck(code_t code) return hasEvexPrefix(code); } -ssize_t GetInputSizeInBytes(instrDesc* id); +ssize_t GetInputSizeInBytes(instrDesc* id) const; bool containsAVXInstruction = false; bool ContainsAVX() @@ -572,7 +577,12 @@ void emitIns_R_C_I(instruction ins, emitAttr attr, regNumber reg1, CORINFO_FIELD void emitIns_R_S_I(instruction ins, emitAttr attr, regNumber reg1, int varx, int offs, int ival); -void emitIns_R_R_A(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, GenTreeIndir* indir); +void emitIns_R_R_A(instruction ins, + emitAttr attr, + regNumber reg1, + regNumber reg2, + GenTreeIndir* indir, + insOpts instOptions = INS_OPTS_NONE); void emitIns_R_R_AR(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber base, int offs); @@ -585,10 +595,21 @@ void emitIns_R_AR_R(instruction ins, int scale, int offs); -void emitIns_R_R_C( - instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, CORINFO_FIELD_HANDLE fldHnd, int offs); - -void emitIns_R_R_S(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, int varx, int offs); +void emitIns_R_R_C(instruction ins, + emitAttr attr, + regNumber reg1, + regNumber reg2, + CORINFO_FIELD_HANDLE fldHnd, + int offs, + insOpts instOptions = INS_OPTS_NONE); + +void emitIns_R_R_S(instruction ins, + emitAttr attr, + regNumber reg1, + regNumber reg2, + int varx, + int offs, + insOpts instOptions = INS_OPTS_NONE); void emitIns_R_R_R(instruction ins, emitAttr attr, regNumber reg1, regNumber reg2, regNumber reg3); @@ -691,11 +712,27 @@ void emitIns_AX_R(instruction ins, emitAttr attr, regNumber ireg, regNumber reg, void emitIns_SIMD_R_R_I(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, int ival); -void emitIns_SIMD_R_R_A(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, GenTreeIndir* indir); -void emitIns_SIMD_R_R_C( - instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, CORINFO_FIELD_HANDLE fldHnd, int offs); +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_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); -void emitIns_SIMD_R_R_S(instruction ins, emitAttr attr, regNumber targetReg, regNumber op1Reg, int varx, int offs); +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); @@ -840,7 +877,6 @@ inline bool emitIsUncondJump(instrDesc* jmp) //------------------------------------------------------------------------ // HasEmbeddedBroadcast: Do we consider embedded broadcast while encoding. -// TODO-XArch-AVX512: Add eventual check on the instrDesc // // Arguments: // id - Instruction descriptor. @@ -850,7 +886,7 @@ inline bool emitIsUncondJump(instrDesc* jmp) // inline bool HasEmbeddedBroadcast(const instrDesc* id) const { - return false; + return id->idIsEvexbContext(); } inline bool HasHighSIMDReg(const instrDesc* id) const; diff --git a/src/coreclr/jit/gcencode.cpp b/src/coreclr/jit/gcencode.cpp index eaa5a584261a37..5cf1eece3e47dc 100644 --- a/src/coreclr/jit/gcencode.cpp +++ b/src/coreclr/jit/gcencode.cpp @@ -3887,7 +3887,7 @@ void GCInfo::gcInfoBlockHdrSave(GcInfoEncoder* gcInfoEncoder, unsigned methodSiz // const int osrOffset = ppInfo->GenericContextArgOffset() - 2 * REGSIZE_BYTES; assert(offset == osrOffset); -#elif defined(TARGET_ARM64) +#elif defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) // PP info has virtual offset. This is also the caller SP offset. // const int osrOffset = ppInfo->GenericContextArgOffset(); @@ -3930,7 +3930,7 @@ void GCInfo::gcInfoBlockHdrSave(GcInfoEncoder* gcInfoEncoder, unsigned methodSiz // const int osrOffset = ppInfo->KeptAliveThisOffset() - 2 * REGSIZE_BYTES; assert(offset == osrOffset); -#elif defined(TARGET_ARM64) +#elif defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) // PP info has virtual offset. This is also the caller SP offset. // const int osrOffset = ppInfo->KeptAliveThisOffset(); diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 833278adf22292..43a2556313adab 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -21,13 +21,13 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX /*****************************************************************************/ const unsigned char GenTree::gtOperKindTable[] = { -#define GTNODE(en, st, cm, ok) ((ok)>K_MASK) + GTK_COMMUTE *cm, +#define GTNODE(en, st, cm, ivn, ok) ((ok)>K_MASK) + GTK_COMMUTE *cm, #include "gtlist.h" }; #ifdef DEBUG const GenTreeDebugOperKind GenTree::gtDebugOperKindTable[] = { -#define GTNODE(en, st, cm, ok) static_cast((ok)&DBK_MASK), +#define GTNODE(en, st, cm, ivn, ok) static_cast((ok)&DBK_MASK), #include "gtlist.h" }; #endif // DEBUG @@ -171,7 +171,7 @@ static void printIndent(IndentStack* indentStack) #if defined(DEBUG) || NODEBASH_STATS || MEASURE_NODE_SIZE || COUNT_AST_OPERS || DUMP_FLOWGRAPHS static const char* opNames[] = { -#define GTNODE(en, st, cm, ok) #en, +#define GTNODE(en, st, cm, ivn, ok) #en, #include "gtlist.h" }; @@ -187,7 +187,7 @@ const char* GenTree::OpName(genTreeOps op) #if MEASURE_NODE_SIZE static const char* opStructNames[] = { -#define GTNODE(en, st, cm, ok) #st, +#define GTNODE(en, st, cm, ivn, ok) #st, #include "gtlist.h" }; @@ -214,7 +214,7 @@ unsigned char GenTree::s_gtNodeSizes[GT_COUNT + 1]; #if NODEBASH_STATS || MEASURE_NODE_SIZE || COUNT_AST_OPERS unsigned char GenTree::s_gtTrueSizes[GT_COUNT + 1]{ -#define GTNODE(en, st, cm, ok) sizeof(st), +#define GTNODE(en, st, cm, ivn, ok) sizeof(st), #include "gtlist.h" }; @@ -12400,11 +12400,21 @@ void Compiler::gtDispTree(GenTree* tree, printf(" (FramesRoot last use)"); } - if (((call->gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0) && - (call->GetSingleInlineCandidateInfo() != nullptr) && - (call->GetSingleInlineCandidateInfo()->exactContextHnd != nullptr)) + if ((call->gtFlags & GTF_CALL_INLINE_CANDIDATE) != 0) { - printf(" (exactContextHnd=0x%p)", dspPtr(call->GetSingleInlineCandidateInfo()->exactContextHnd)); + InlineCandidateInfo* inlineInfo; + if (call->IsGuardedDevirtualizationCandidate()) + { + inlineInfo = call->GetGDVCandidateInfo(0); + } + else + { + inlineInfo = call->GetSingleInlineCandidateInfo(); + } + if ((inlineInfo != nullptr) && (inlineInfo->exactContextHnd != nullptr)) + { + printf(" (exactContextHnd=0x%p)", dspPtr(inlineInfo->exactContextHnd)); + } } gtDispCommonEndLine(tree); @@ -17878,6 +17888,7 @@ CORINFO_CLASS_HANDLE Compiler::gtGetClassHandle(GenTree* tree, bool* pIsExact, b { // if we managed to get a class handle it's definitely not null *pIsNonNull = true; + *pIsExact = true; } } break; @@ -19065,6 +19076,18 @@ bool GenTree::isContainableHWIntrinsic() const return true; } + case NI_SSE3_MoveAndDuplicate: + case NI_AVX_BroadcastScalarToVector128: + case NI_AVX2_BroadcastScalarToVector128: + case NI_AVX_BroadcastScalarToVector256: + case NI_AVX2_BroadcastScalarToVector256: + case NI_AVX512F_BroadcastScalarToVector512: + { + // These intrinsic operations are contained as part of the operand of embedded broadcast compatible + // instruction + return true; + } + default: { return false; @@ -20418,7 +20441,20 @@ GenTree* Compiler::gtNewSimdCmpOpNode( #if defined(TARGET_XARCH) case GT_EQ: { - if (simdSize == 32) + if (simdSize == 64) + { + assert(IsBaselineVector512IsaSupportedDebugOnly()); + + if (varTypeIsSmall(simdBaseType)) + { + intrinsic = NI_AVX512BW_CompareEqual; + } + else + { + intrinsic = NI_AVX512F_CompareEqual; + } + } + else if (simdSize == 32) { assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); @@ -20432,17 +20468,15 @@ GenTree* Compiler::gtNewSimdCmpOpNode( intrinsic = NI_AVX2_CompareEqual; } } - else if (simdSize == 64) - { - assert(IsBaselineVector512IsaSupportedDebugOnly()); - intrinsic = NI_AVX512F_CompareEqualSpecial; - } else if (simdBaseType == TYP_FLOAT) { + assert((simdSize == 8) || (simdSize == 12) || (simdSize == 16)); intrinsic = NI_SSE_CompareEqual; } else if (varTypeIsLong(simdBaseType)) { + assert(simdSize == 16); + if (compOpportunisticallyDependsOn(InstructionSet_SSE41)) { intrinsic = NI_SSE41_CompareEqual; @@ -20471,6 +20505,7 @@ GenTree* Compiler::gtNewSimdCmpOpNode( } else { + assert(simdSize == 16); intrinsic = NI_SSE2_CompareEqual; } break; @@ -20478,6 +20513,37 @@ GenTree* Compiler::gtNewSimdCmpOpNode( case GT_GE: { + if (IsBaselineVector512IsaSupported()) + { + if (simdSize == 64) + { + if (varTypeIsSmall(simdBaseType)) + { + intrinsic = NI_AVX512BW_CompareGreaterThanOrEqual; + } + else + { + intrinsic = NI_AVX512F_CompareGreaterThanOrEqual; + } + break; + } + else if (!varTypeIsFloating(simdBaseType)) + { + assert((simdSize == 16) || (simdSize == 32)); + + if (varTypeIsSmall(simdBaseType)) + { + intrinsic = NI_AVX512BW_VL_CompareGreaterThanOrEqual; + } + else + { + intrinsic = NI_AVX512F_VL_CompareGreaterThanOrEqual; + } + + break; + } + } + if (simdSize == 32) { assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); @@ -20487,17 +20553,14 @@ GenTree* Compiler::gtNewSimdCmpOpNode( intrinsic = NI_AVX_CompareGreaterThanOrEqual; } } - else if (simdSize == 64) - { - assert(IsBaselineVector512IsaSupportedDebugOnly()); - intrinsic = NI_AVX512F_CompareGreaterThanOrEqualSpecial; - } else if (simdBaseType == TYP_FLOAT) { + assert((simdSize == 8) || (simdSize == 12) || (simdSize == 16)); intrinsic = NI_SSE_CompareGreaterThanOrEqual; } else if (simdBaseType == TYP_DOUBLE) { + assert(simdSize == 16); intrinsic = NI_SSE2_CompareGreaterThanOrEqual; } @@ -20545,6 +20608,37 @@ GenTree* Compiler::gtNewSimdCmpOpNode( case GT_GT: { + if (IsBaselineVector512IsaSupported()) + { + if (simdSize == 64) + { + if (varTypeIsSmall(simdBaseType)) + { + intrinsic = NI_AVX512BW_CompareGreaterThan; + } + else + { + intrinsic = NI_AVX512F_CompareGreaterThan; + } + break; + } + else if (varTypeIsUnsigned(simdBaseType)) + { + assert((simdSize == 16) || (simdSize == 32)); + + if (varTypeIsSmall(simdBaseType)) + { + intrinsic = NI_AVX512BW_VL_CompareGreaterThan; + } + else + { + intrinsic = NI_AVX512F_VL_CompareGreaterThan; + } + + break; + } + } + if (varTypeIsUnsigned(simdBaseType)) { // Vector of byte, ushort, uint and ulong: @@ -20638,17 +20732,15 @@ GenTree* Compiler::gtNewSimdCmpOpNode( intrinsic = NI_AVX2_CompareGreaterThan; } } - else if (simdSize == 64) - { - assert(IsBaselineVector512IsaSupportedDebugOnly()); - intrinsic = NI_AVX512F_CompareGreaterThanSpecial; - } else if (simdBaseType == TYP_FLOAT) { + assert((simdSize == 8) || (simdSize == 12) || (simdSize == 16)); intrinsic = NI_SSE_CompareGreaterThan; } else if (varTypeIsLong(simdBaseType)) { + assert(simdSize == 16); + if (compOpportunisticallyDependsOn(InstructionSet_SSE42)) { intrinsic = NI_SSE42_CompareGreaterThan; @@ -20710,6 +20802,7 @@ GenTree* Compiler::gtNewSimdCmpOpNode( } else { + assert(simdSize == 16); intrinsic = NI_SSE2_CompareGreaterThan; } break; @@ -20717,6 +20810,37 @@ GenTree* Compiler::gtNewSimdCmpOpNode( case GT_LE: { + if (IsBaselineVector512IsaSupported()) + { + if (simdSize == 64) + { + if (varTypeIsSmall(simdBaseType)) + { + intrinsic = NI_AVX512BW_CompareLessThanOrEqual; + } + else + { + intrinsic = NI_AVX512F_CompareLessThanOrEqual; + } + break; + } + else if (!varTypeIsFloating(simdBaseType)) + { + assert((simdSize == 16) || (simdSize == 32)); + + if (varTypeIsSmall(simdBaseType)) + { + intrinsic = NI_AVX512BW_VL_CompareLessThanOrEqual; + } + else + { + intrinsic = NI_AVX512F_VL_CompareLessThanOrEqual; + } + + break; + } + } + if (simdSize == 32) { assert(compIsaSupportedDebugOnly(InstructionSet_AVX)); @@ -20726,17 +20850,14 @@ GenTree* Compiler::gtNewSimdCmpOpNode( intrinsic = NI_AVX_CompareLessThanOrEqual; } } - else if (simdSize == 64) - { - assert(IsBaselineVector512IsaSupportedDebugOnly()); - intrinsic = NI_AVX512F_CompareLessThanOrEqualSpecial; - } else if (simdBaseType == TYP_FLOAT) { + assert((simdSize == 8) || (simdSize == 12) || (simdSize == 16)); intrinsic = NI_SSE_CompareLessThanOrEqual; } else if (simdBaseType == TYP_DOUBLE) { + assert(simdSize == 16); intrinsic = NI_SSE2_CompareLessThanOrEqual; } @@ -20784,6 +20905,37 @@ GenTree* Compiler::gtNewSimdCmpOpNode( case GT_LT: { + if (IsBaselineVector512IsaSupported()) + { + if (simdSize == 64) + { + if (varTypeIsSmall(simdBaseType)) + { + intrinsic = NI_AVX512BW_CompareLessThan; + } + else + { + intrinsic = NI_AVX512F_CompareLessThan; + } + break; + } + else if (varTypeIsUnsigned(simdBaseType)) + { + assert((simdSize == 16) || (simdSize == 32)); + + if (varTypeIsSmall(simdBaseType)) + { + intrinsic = NI_AVX512BW_VL_CompareLessThan; + } + else + { + intrinsic = NI_AVX512F_VL_CompareLessThan; + } + + break; + } + } + if (varTypeIsUnsigned(simdBaseType)) { // Vector of byte, ushort, uint and ulong: @@ -20877,17 +21029,15 @@ GenTree* Compiler::gtNewSimdCmpOpNode( intrinsic = NI_AVX2_CompareLessThan; } } - else if (simdSize == 64) - { - assert(IsBaselineVector512IsaSupportedDebugOnly()); - intrinsic = NI_AVX512F_CompareLessThanSpecial; - } else if (simdBaseType == TYP_FLOAT) { + assert((simdSize == 8) || (simdSize == 12) || (simdSize == 16)); intrinsic = NI_SSE_CompareLessThan; } else if (varTypeIsLong(simdBaseType)) { + assert(simdSize == 16); + if (compOpportunisticallyDependsOn(InstructionSet_SSE42)) { intrinsic = NI_SSE42_CompareLessThan; @@ -20949,6 +21099,7 @@ GenTree* Compiler::gtNewSimdCmpOpNode( } else { + assert(simdSize == 16); intrinsic = NI_SSE2_CompareLessThan; } break; @@ -21034,15 +21185,7 @@ GenTree* Compiler::gtNewSimdCmpOpNode( assert(intrinsic != NI_Illegal); #if defined(TARGET_XARCH) - if (simdSize != 64) - { - return gtNewSimdHWIntrinsicNode(type, op1, op2, intrinsic, simdBaseJitType, simdSize); - } - else - { - GenTree* cmp = gtNewSimdHWIntrinsicNode(TYP_MASK, op1, op2, intrinsic, simdBaseJitType, simdSize); - return gtNewSimdHWIntrinsicNode(type, cmp, NI_AVX512F_MoveMaskToVectorSpecial, simdBaseJitType, simdSize); - } + return gtNewSimdHWIntrinsicNode(type, op1, op2, intrinsic, simdBaseJitType, simdSize); #else return gtNewSimdHWIntrinsicNode(type, op1, op2, intrinsic, simdBaseJitType, simdSize); #endif @@ -21093,125 +21236,8 @@ GenTree* Compiler::gtNewSimdCmpOpAllNode( } case GT_GE: - { - // We want to generate a comparison along the lines of - // GT_XX(op1, op2).As() == Vector128.AllBitsSet - - if (simdSize == 32) - { - // TODO-XArch-CQ: It's a non-trivial amount of work to support these - // for floating-point while only utilizing AVX. It would require, among - // other things, inverting the comparison and potentially support for a - // new Avx.TestNotZ intrinsic to ensure the codegen remains efficient. - assert(compIsaSupportedDebugOnly(InstructionSet_AVX2)); - intrinsic = NI_Vector256_op_Equality; - } - else if (simdSize == 64) - { - assert(IsBaselineVector512IsaSupportedDebugOnly()); - intrinsic = NI_Vector512_GreaterThanOrEqualAll; - break; - } - else - { - intrinsic = NI_Vector128_op_Equality; - } - - op1 = gtNewSimdCmpOpNode(op, simdType, op1, op2, simdBaseJitType, simdSize); - op2 = gtNewAllBitsSetConNode(simdType); - - if (simdBaseType == TYP_FLOAT) - { - simdBaseType = TYP_INT; - simdBaseJitType = CORINFO_TYPE_INT; - } - else if (simdBaseType == TYP_DOUBLE) - { - simdBaseType = TYP_LONG; - simdBaseJitType = CORINFO_TYPE_LONG; - } - break; - } case GT_GT: - { - // We want to generate a comparison along the lines of - // GT_XX(op1, op2).As() == Vector128.AllBitsSet - - if (simdSize == 32) - { - // TODO-XArch-CQ: It's a non-trivial amount of work to support these - // for floating-point while only utilizing AVX. It would require, among - // other things, inverting the comparison and potentially support for a - // new Avx.TestNotZ intrinsic to ensure the codegen remains efficient. - assert(compIsaSupportedDebugOnly(InstructionSet_AVX2)); - intrinsic = NI_Vector256_op_Equality; - } - else if (simdSize == 64) - { - assert(IsBaselineVector512IsaSupportedDebugOnly()); - intrinsic = NI_Vector512_GreaterThanAll; - break; - } - else - { - intrinsic = NI_Vector128_op_Equality; - } - - op1 = gtNewSimdCmpOpNode(op, simdType, op1, op2, simdBaseJitType, simdSize); - op2 = gtNewAllBitsSetConNode(simdType); - - if (simdBaseType == TYP_FLOAT) - { - simdBaseType = TYP_INT; - simdBaseJitType = CORINFO_TYPE_INT; - } - else if (simdBaseType == TYP_DOUBLE) - { - simdBaseType = TYP_LONG; - simdBaseJitType = CORINFO_TYPE_LONG; - } - break; - } case GT_LE: - { - // We want to generate a comparison along the lines of - // GT_XX(op1, op2).As() == Vector128.AllBitsSet - - if (simdSize == 32) - { - // TODO-XArch-CQ: It's a non-trivial amount of work to support these - // for floating-point while only utilizing AVX. It would require, among - // other things, inverting the comparison and potentially support for a - // new Avx.TestNotZ intrinsic to ensure the codegen remains efficient. - assert(compIsaSupportedDebugOnly(InstructionSet_AVX2)); - intrinsic = NI_Vector256_op_Equality; - } - else if (simdSize == 64) - { - assert(IsBaselineVector512IsaSupportedDebugOnly()); - intrinsic = NI_Vector512_LessThanOrEqualAll; - break; - } - else - { - intrinsic = NI_Vector128_op_Equality; - } - - op1 = gtNewSimdCmpOpNode(op, simdType, op1, op2, simdBaseJitType, simdSize); - op2 = gtNewAllBitsSetConNode(simdType); - - if (simdBaseType == TYP_FLOAT) - { - simdBaseType = TYP_INT; - simdBaseJitType = CORINFO_TYPE_INT; - } - else if (simdBaseType == TYP_DOUBLE) - { - simdBaseType = TYP_LONG; - simdBaseJitType = CORINFO_TYPE_LONG; - } - break; - } case GT_LT: { // We want to generate a comparison along the lines of @@ -21229,8 +21255,7 @@ GenTree* Compiler::gtNewSimdCmpOpAllNode( else if (simdSize == 64) { assert(IsBaselineVector512IsaSupportedDebugOnly()); - intrinsic = NI_Vector512_LessThanAll; - break; + intrinsic = NI_Vector512_op_Equality; } else { @@ -21471,14 +21496,12 @@ GenTree* Compiler::gtNewSimdCndSelNode( return gtNewSimdTernaryLogicNode(type, op1, op2, op3, control, simdBaseJitType, simdSize); } + assert(simdSize != 64); + if (simdSize == 32) { intrinsic = NI_Vector256_ConditionalSelect; } - else if (simdSize == 64) - { - intrinsic = NI_Vector512_ConditionalSelect; - } else { intrinsic = NI_Vector128_ConditionalSelect; @@ -21908,6 +21931,7 @@ GenTree* Compiler::gtNewSimdDotProdNode( #if defined(TARGET_XARCH) assert(!varTypeIsByte(simdBaseType) && !varTypeIsLong(simdBaseType)); + assert(simdSize != 64); if (simdSize == 32) { @@ -23804,6 +23828,7 @@ GenTree* Compiler::gtNewSimdSumNode(var_types type, GenTree* op1, CorInfoType si #if defined(TARGET_XARCH) assert(!varTypeIsByte(simdBaseType) && !varTypeIsLong(simdBaseType)); + assert(simdSize != 64); // HorizontalAdd combines pairs so we need log2(vectorLength) passes to sum all elements together. unsigned vectorLength = getSIMDVectorLength(simdSize, simdBaseType); @@ -24771,6 +24796,25 @@ GenTreeHWIntrinsic* Compiler::gtNewScalarHWIntrinsicNode( GenTreeHWIntrinsic(type, getAllocator(CMK_ASTNode), hwIntrinsicID, CORINFO_TYPE_UNDEF, 0, op1, op2, op3); } +//------------------------------------------------------------------------ +// OperIsHWIntrinsic: Is this a hwintrinsic with the specified id +// +// Arguments: +// intrinsicId -- the id to compare with the current node +// +// Return Value: +// true if the node is a hwintrinsic intrinsic with the specified id +// otherwise; false +// +bool GenTree::OperIsHWIntrinsic(NamedIntrinsic intrinsicId) const +{ + if (OperIsHWIntrinsic()) + { + return AsHWIntrinsic()->GetHWIntrinsicId() == intrinsicId; + } + return false; +} + //------------------------------------------------------------------------ // OperIsMemoryLoad: Does this HWI node have memory load semantics? // @@ -24998,6 +25042,75 @@ bool GenTreeHWIntrinsic::OperIsMemoryStoreOrBarrier() const } } +//------------------------------------------------------------------------ +// OperIsEmbBroadcastCompatible: Checks if the intrinsic is a embedded broadcast compatible inintrsic. +// +// Return Value: +// true if the intrinsic node lowering instruction is embedded broadcast compatible. +// +bool GenTreeHWIntrinsic::OperIsEmbBroadcastCompatible() const +{ + return HWIntrinsicInfo::IsEmbBroadcastCompatible(GetHWIntrinsicId()); +} + +//------------------------------------------------------------------------ +// OperIsBroadcastScalar: Is this HWIntrinsic a broadcast node from scalar. +// +// Return Value: +// Whether "this" is a broadcast node from scalar. +// +bool GenTreeHWIntrinsic::OperIsBroadcastScalar() const +{ +#if defined(TARGET_XARCH) + NamedIntrinsic intrinsicId = GetHWIntrinsicId(); + switch (intrinsicId) + { + case NI_AVX2_BroadcastScalarToVector128: + case NI_AVX2_BroadcastScalarToVector256: + case NI_AVX_BroadcastScalarToVector128: + case NI_AVX_BroadcastScalarToVector256: + case NI_SSE3_MoveAndDuplicate: + case NI_AVX512F_BroadcastScalarToVector512: + return true; + default: + return false; + } +#else + return false; +#endif +} + +//------------------------------------------------------------------------ +// OperIsCreateScalarUnsafe: Is this HWIntrinsic a CreateScalarUnsafe node. +// +// Return Value: +// Whether "this" is a CreateScalarUnsafe node. +// +bool GenTreeHWIntrinsic::OperIsCreateScalarUnsafe() const +{ + NamedIntrinsic intrinsicId = GetHWIntrinsicId(); + + switch (intrinsicId) + { +#if defined(TARGET_ARM64) + case NI_Vector64_CreateScalarUnsafe: +#endif // TARGET_ARM64 + case NI_Vector128_CreateScalarUnsafe: +#if defined(TARGET_XARCH) + case NI_Vector256_CreateScalarUnsafe: + case NI_Vector512_CreateScalarUnsafe: +#endif // TARGET_XARCH + { + return true; + } + + default: + { + return false; + } + } +} + //------------------------------------------------------------------------------ // OperRequiresAsgFlag : Check whether the operation requires GTF_ASG flag regardless // of the children's flags. diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index e5f3e11f426792..4483cd73812a05 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -554,6 +554,7 @@ enum GenTreeFlags : unsigned int GTF_MDARRLEN_NONFAULTING = 0x20000000, // GT_MDARR_LENGTH -- An MD array length operation that cannot fault. Same as GT_IND_NONFAULTING. GTF_MDARRLOWERBOUND_NONFAULTING = 0x20000000, // GT_MDARR_LOWER_BOUND -- An MD array lower bound operation that cannot fault. Same as GT_IND_NONFAULTING. + }; inline constexpr GenTreeFlags operator ~(GenTreeFlags a) @@ -1086,7 +1087,7 @@ struct GenTree return TypeIs(type) || TypeIs(rest...); } - static bool StaticOperIs(genTreeOps operCompare, genTreeOps oper) + static constexpr bool StaticOperIs(genTreeOps operCompare, genTreeOps oper) { return operCompare == oper; } @@ -1650,6 +1651,8 @@ struct GenTree return OperIsHWIntrinsic(gtOper); } + bool OperIsHWIntrinsic(NamedIntrinsic intrinsicId) const; + // This is here for cleaner GT_LONG #ifdefs. static bool OperIsLong(genTreeOps gtOper) { @@ -6242,6 +6245,9 @@ struct GenTreeHWIntrinsic : public GenTreeJitIntrinsic bool OperIsMemoryStore(GenTree** pAddr = nullptr) const; bool OperIsMemoryLoadOrStore() const; bool OperIsMemoryStoreOrBarrier() const; + bool OperIsEmbBroadcastCompatible() const; + bool OperIsBroadcastScalar() const; + bool OperIsCreateScalarUnsafe() const; bool OperRequiresAsgFlag() const; bool OperRequiresCallFlag() const; diff --git a/src/coreclr/jit/gentreeopsdef.h b/src/coreclr/jit/gentreeopsdef.h index 9e8e91508c0177..acffd4a12045de 100644 --- a/src/coreclr/jit/gentreeopsdef.h +++ b/src/coreclr/jit/gentreeopsdef.h @@ -8,7 +8,7 @@ enum genTreeOps : BYTE { -#define GTNODE(en, st, cm, ok) GT_##en, +#define GTNODE(en, st, cm, ivn, ok) GT_##en, #include "gtlist.h" GT_COUNT, diff --git a/src/coreclr/jit/gtlist.h b/src/coreclr/jit/gtlist.h index 33925ae801a87f..b3a3d2dbb470c9 100644 --- a/src/coreclr/jit/gtlist.h +++ b/src/coreclr/jit/gtlist.h @@ -11,164 +11,165 @@ // Node enum // , GenTree struct flavor // ,commutative -// ,oper kind | DEBUG oper kind +// ,illegal as VN func +// ,oper kind | DEBUG oper kind -GTNODE(NONE , char ,0,GTK_SPECIAL) +GTNODE(NONE , char ,0,0,GTK_SPECIAL) //----------------------------------------------------------------------------- // Nodes related to locals: //----------------------------------------------------------------------------- -GTNODE(PHI , GenTreePhi ,0,GTK_SPECIAL) // phi node for ssa. -GTNODE(PHI_ARG , GenTreePhiArg ,0,GTK_LEAF) // phi(phiarg, phiarg, phiarg) -GTNODE(LCL_VAR , GenTreeLclVar ,0,GTK_LEAF) // local variable -GTNODE(LCL_FLD , GenTreeLclFld ,0,GTK_LEAF) // field in a non-primitive variable -GTNODE(STORE_LCL_VAR , GenTreeLclVar ,0,GTK_UNOP|GTK_EXOP|GTK_NOVALUE|GTK_STORE) // store to local variable -GTNODE(STORE_LCL_FLD , GenTreeLclFld ,0,GTK_UNOP|GTK_EXOP|GTK_NOVALUE|GTK_STORE) // store to a part of the variable -GTNODE(LCL_ADDR , GenTreeLclFld ,0,GTK_LEAF) // local address +GTNODE(PHI , GenTreePhi ,0,0,GTK_SPECIAL) // phi node for ssa. +GTNODE(PHI_ARG , GenTreePhiArg ,0,0,GTK_LEAF) // phi(phiarg, phiarg, phiarg) +GTNODE(LCL_VAR , GenTreeLclVar ,0,0,GTK_LEAF) // local variable +GTNODE(LCL_FLD , GenTreeLclFld ,0,0,GTK_LEAF) // field in a non-primitive variable +GTNODE(STORE_LCL_VAR , GenTreeLclVar ,0,1,GTK_UNOP|GTK_EXOP|GTK_NOVALUE|GTK_STORE) // store to local variable +GTNODE(STORE_LCL_FLD , GenTreeLclFld ,0,1,GTK_UNOP|GTK_EXOP|GTK_NOVALUE|GTK_STORE) // store to a part of the variable +GTNODE(LCL_ADDR , GenTreeLclFld ,0,0,GTK_LEAF) // local address //----------------------------------------------------------------------------- // Leaf nodes (i.e. these nodes have no sub-operands): //----------------------------------------------------------------------------- -GTNODE(CATCH_ARG , GenTree ,0,GTK_LEAF) // Exception object in a catch block -GTNODE(LABEL , GenTree ,0,GTK_LEAF) // Jump-target -GTNODE(JMP , GenTreeVal ,0,GTK_LEAF|GTK_NOVALUE) // Jump to another function -GTNODE(FTN_ADDR , GenTreeFptrVal ,0,GTK_LEAF) // Address of a function -GTNODE(RET_EXPR , GenTreeRetExpr ,0,GTK_LEAF|DBK_NOTLIR) // Place holder for the return expression from an inline candidate +GTNODE(CATCH_ARG , GenTree ,0,0,GTK_LEAF) // Exception object in a catch block +GTNODE(LABEL , GenTree ,0,0,GTK_LEAF) // Jump-target +GTNODE(JMP , GenTreeVal ,0,0,GTK_LEAF|GTK_NOVALUE) // Jump to another function +GTNODE(FTN_ADDR , GenTreeFptrVal ,0,0,GTK_LEAF) // Address of a function +GTNODE(RET_EXPR , GenTreeRetExpr ,0,0,GTK_LEAF|DBK_NOTLIR) // Place holder for the return expression from an inline candidate //----------------------------------------------------------------------------- // Constant nodes: //----------------------------------------------------------------------------- -GTNODE(CNS_INT , GenTreeIntCon ,0,GTK_LEAF) -GTNODE(CNS_LNG , GenTreeLngCon ,0,GTK_LEAF) -GTNODE(CNS_DBL , GenTreeDblCon ,0,GTK_LEAF) -GTNODE(CNS_STR , GenTreeStrCon ,0,GTK_LEAF) -GTNODE(CNS_VEC , GenTreeVecCon ,0,GTK_LEAF) +GTNODE(CNS_INT , GenTreeIntCon ,0,0,GTK_LEAF) +GTNODE(CNS_LNG , GenTreeLngCon ,0,0,GTK_LEAF) +GTNODE(CNS_DBL , GenTreeDblCon ,0,0,GTK_LEAF) +GTNODE(CNS_STR , GenTreeStrCon ,0,0,GTK_LEAF) +GTNODE(CNS_VEC , GenTreeVecCon ,0,0,GTK_LEAF) //----------------------------------------------------------------------------- // Unary operators (1 operand): //----------------------------------------------------------------------------- -GTNODE(NOT , GenTreeOp ,0,GTK_UNOP) -GTNODE(NOP , GenTree ,0,GTK_UNOP|DBK_NOCONTAIN) -GTNODE(NEG , GenTreeOp ,0,GTK_UNOP) +GTNODE(NOT , GenTreeOp ,0,0,GTK_UNOP) +GTNODE(NOP , GenTree ,0,0,GTK_UNOP|DBK_NOCONTAIN) +GTNODE(NEG , GenTreeOp ,0,0,GTK_UNOP) -GTNODE(INTRINSIC , GenTreeIntrinsic ,0,GTK_BINOP|GTK_EXOP) +GTNODE(INTRINSIC , GenTreeIntrinsic ,0,0,GTK_BINOP|GTK_EXOP) -GTNODE(LOCKADD , GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) -GTNODE(XAND , GenTreeOp ,0,GTK_BINOP) -GTNODE(XORR , GenTreeOp ,0,GTK_BINOP) -GTNODE(XADD , GenTreeOp ,0,GTK_BINOP) -GTNODE(XCHG , GenTreeOp ,0,GTK_BINOP) -GTNODE(CMPXCHG , GenTreeCmpXchg ,0,GTK_SPECIAL) -GTNODE(MEMORYBARRIER , GenTree ,0,GTK_LEAF|GTK_NOVALUE) +GTNODE(LOCKADD , GenTreeOp ,0,1,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) +GTNODE(XAND , GenTreeOp ,0,1,GTK_BINOP) +GTNODE(XORR , GenTreeOp ,0,1,GTK_BINOP) +GTNODE(XADD , GenTreeOp ,0,1,GTK_BINOP) +GTNODE(XCHG , GenTreeOp ,0,1,GTK_BINOP) +GTNODE(CMPXCHG , GenTreeCmpXchg ,0,1,GTK_SPECIAL) +GTNODE(MEMORYBARRIER , GenTree ,0,0,GTK_LEAF|GTK_NOVALUE) -GTNODE(KEEPALIVE , GenTree ,0,GTK_UNOP|GTK_NOVALUE) // keep operand alive, generate no code, produce no result +GTNODE(KEEPALIVE , GenTree ,0,0,GTK_UNOP|GTK_NOVALUE) // keep operand alive, generate no code, produce no result -GTNODE(CAST , GenTreeCast ,0,GTK_UNOP|GTK_EXOP) // conversion to another type +GTNODE(CAST , GenTreeCast ,0,0,GTK_UNOP|GTK_EXOP) // conversion to another type #if defined(TARGET_ARM) -GTNODE(BITCAST , GenTreeMultiRegOp ,0,GTK_UNOP) // reinterpretation of bits as another type +GTNODE(BITCAST , GenTreeMultiRegOp ,0,1,GTK_UNOP) // reinterpretation of bits as another type #else -GTNODE(BITCAST , GenTreeOp ,0,GTK_UNOP) // reinterpretation of bits as another type +GTNODE(BITCAST , GenTreeOp ,0,1,GTK_UNOP) // reinterpretation of bits as another type #endif -GTNODE(CKFINITE , GenTreeOp ,0,GTK_UNOP|DBK_NOCONTAIN) // Check for NaN -GTNODE(LCLHEAP , GenTreeOp ,0,GTK_UNOP|DBK_NOCONTAIN) // alloca() +GTNODE(CKFINITE , GenTreeOp ,0,1,GTK_UNOP|DBK_NOCONTAIN) // Check for NaN +GTNODE(LCLHEAP , GenTreeOp ,0,1,GTK_UNOP|DBK_NOCONTAIN) // alloca() -GTNODE(BOUNDS_CHECK , GenTreeBoundsChk ,0,GTK_BINOP|GTK_EXOP|GTK_NOVALUE) // a bounds check - for arrays/spans/SIMDs/HWINTRINSICs +GTNODE(BOUNDS_CHECK , GenTreeBoundsChk ,0,1,GTK_BINOP|GTK_EXOP|GTK_NOVALUE) // a bounds check - for arrays/spans/SIMDs/HWINTRINSICs -GTNODE(IND , GenTreeIndir ,0,GTK_UNOP) // Load indirection -GTNODE(STOREIND , GenTreeStoreInd ,0,GTK_BINOP|GTK_EXOP|GTK_NOVALUE|GTK_STORE) // Store indirection -GTNODE(BLK , GenTreeBlk ,0,GTK_UNOP|GTK_EXOP) // Struct load -GTNODE(STORE_BLK , GenTreeBlk ,0,GTK_BINOP|GTK_EXOP|GTK_NOVALUE|GTK_STORE) // Struct store -GTNODE(STORE_DYN_BLK , GenTreeStoreDynBlk ,0,GTK_SPECIAL|GTK_NOVALUE) // Dynamically sized block store, with native uint size -GTNODE(NULLCHECK , GenTreeIndir ,0,GTK_UNOP|GTK_NOVALUE) // Null checks the source +GTNODE(IND , GenTreeIndir ,0,1,GTK_UNOP) // Load indirection +GTNODE(STOREIND , GenTreeStoreInd ,0,1,GTK_BINOP|GTK_EXOP|GTK_NOVALUE|GTK_STORE) // Store indirection +GTNODE(BLK , GenTreeBlk ,0,1,GTK_UNOP|GTK_EXOP) // Struct load +GTNODE(STORE_BLK , GenTreeBlk ,0,1,GTK_BINOP|GTK_EXOP|GTK_NOVALUE|GTK_STORE) // Struct store +GTNODE(STORE_DYN_BLK , GenTreeStoreDynBlk ,0,1,GTK_SPECIAL|GTK_NOVALUE) // Dynamically sized block store, with native uint size +GTNODE(NULLCHECK , GenTreeIndir ,0,1,GTK_UNOP|GTK_NOVALUE) // Null checks the source -GTNODE(ARR_LENGTH , GenTreeArrLen ,0,GTK_UNOP|GTK_EXOP) // single-dimension (SZ) array length -GTNODE(MDARR_LENGTH , GenTreeMDArr ,0,GTK_UNOP|GTK_EXOP) // multi-dimension (MD) array length of a specific dimension -GTNODE(MDARR_LOWER_BOUND, GenTreeMDArr ,0,GTK_UNOP|GTK_EXOP) // multi-dimension (MD) array lower bound of a specific dimension -GTNODE(FIELD_ADDR , GenTreeFieldAddr ,0,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // Field address -GTNODE(ALLOCOBJ , GenTreeAllocObj ,0,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // object allocator +GTNODE(ARR_LENGTH , GenTreeArrLen ,0,0,GTK_UNOP|GTK_EXOP) // single-dimension (SZ) array length +GTNODE(MDARR_LENGTH , GenTreeMDArr ,0,1,GTK_UNOP|GTK_EXOP) // multi-dimension (MD) array length of a specific dimension +GTNODE(MDARR_LOWER_BOUND, GenTreeMDArr ,0,1,GTK_UNOP|GTK_EXOP) // multi-dimension (MD) array lower bound of a specific dimension +GTNODE(FIELD_ADDR , GenTreeFieldAddr ,0,0,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // Field address +GTNODE(ALLOCOBJ , GenTreeAllocObj ,0,0,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // object allocator -GTNODE(INIT_VAL , GenTreeOp ,0,GTK_UNOP) // Initialization value for an initBlk +GTNODE(INIT_VAL , GenTreeOp ,0,1,GTK_UNOP) // Initialization value for an initBlk -GTNODE(BOX , GenTreeBox ,0,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // Marks its first operands (a local) as being a box -GTNODE(RUNTIMELOOKUP , GenTreeRuntimeLookup, 0,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // Runtime handle lookup -GTNODE(ARR_ADDR , GenTreeArrAddr ,0,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // Wraps an array address expression +GTNODE(BOX , GenTreeBox ,0,1,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // Marks its first operands (a local) as being a box +GTNODE(RUNTIMELOOKUP , GenTreeRuntimeLookup, 0,0,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // Runtime handle lookup +GTNODE(ARR_ADDR , GenTreeArrAddr ,0,1,GTK_UNOP|GTK_EXOP|DBK_NOTLIR) // Wraps an array address expression -GTNODE(BSWAP , GenTreeOp ,0,GTK_UNOP) // Byte swap (32-bit or 64-bit) -GTNODE(BSWAP16 , GenTreeOp ,0,GTK_UNOP) // Byte swap lower 16-bits and zero upper 16 bits +GTNODE(BSWAP , GenTreeOp ,0,0,GTK_UNOP) // Byte swap (32-bit or 64-bit) +GTNODE(BSWAP16 , GenTreeOp ,0,0,GTK_UNOP) // Byte swap lower 16-bits and zero upper 16 bits -GTNODE(LZCNT , GenTreeOp ,0,GTK_UNOP) // Leading Zero Count - Only used for SIMD VN evaluation today +GTNODE(LZCNT , GenTreeOp ,0,0,GTK_UNOP) // Leading Zero Count - Only used for SIMD VN evaluation today //----------------------------------------------------------------------------- // Binary operators (2 operands): //----------------------------------------------------------------------------- -GTNODE(ADD , GenTreeOp ,1,GTK_BINOP) -GTNODE(SUB , GenTreeOp ,0,GTK_BINOP) -GTNODE(MUL , GenTreeOp ,1,GTK_BINOP) -GTNODE(DIV , GenTreeOp ,0,GTK_BINOP) -GTNODE(MOD , GenTreeOp ,0,GTK_BINOP) +GTNODE(ADD , GenTreeOp ,1,0,GTK_BINOP) +GTNODE(SUB , GenTreeOp ,0,0,GTK_BINOP) +GTNODE(MUL , GenTreeOp ,1,0,GTK_BINOP) +GTNODE(DIV , GenTreeOp ,0,0,GTK_BINOP) +GTNODE(MOD , GenTreeOp ,0,0,GTK_BINOP) -GTNODE(UDIV , GenTreeOp ,0,GTK_BINOP) -GTNODE(UMOD , GenTreeOp ,0,GTK_BINOP) +GTNODE(UDIV , GenTreeOp ,0,0,GTK_BINOP) +GTNODE(UMOD , GenTreeOp ,0,0,GTK_BINOP) -GTNODE(OR , GenTreeOp ,1,GTK_BINOP) -GTNODE(XOR , GenTreeOp ,1,GTK_BINOP) -GTNODE(AND , GenTreeOp ,1,GTK_BINOP) +GTNODE(OR , GenTreeOp ,1,0,GTK_BINOP) +GTNODE(XOR , GenTreeOp ,1,0,GTK_BINOP) +GTNODE(AND , GenTreeOp ,1,0,GTK_BINOP) -GTNODE(LSH , GenTreeOp ,0,GTK_BINOP) -GTNODE(RSH , GenTreeOp ,0,GTK_BINOP) -GTNODE(RSZ , GenTreeOp ,0,GTK_BINOP) -GTNODE(ROL , GenTreeOp ,0,GTK_BINOP) -GTNODE(ROR , GenTreeOp ,0,GTK_BINOP) +GTNODE(LSH , GenTreeOp ,0,0,GTK_BINOP) +GTNODE(RSH , GenTreeOp ,0,0,GTK_BINOP) +GTNODE(RSZ , GenTreeOp ,0,0,GTK_BINOP) +GTNODE(ROL , GenTreeOp ,0,0,GTK_BINOP) +GTNODE(ROR , GenTreeOp ,0,0,GTK_BINOP) -GTNODE(EQ , GenTreeOp ,0,GTK_BINOP) -GTNODE(NE , GenTreeOp ,0,GTK_BINOP) -GTNODE(LT , GenTreeOp ,0,GTK_BINOP) -GTNODE(LE , GenTreeOp ,0,GTK_BINOP) -GTNODE(GE , GenTreeOp ,0,GTK_BINOP) -GTNODE(GT , GenTreeOp ,0,GTK_BINOP) +GTNODE(EQ , GenTreeOp ,0,0,GTK_BINOP) +GTNODE(NE , GenTreeOp ,0,0,GTK_BINOP) +GTNODE(LT , GenTreeOp ,0,0,GTK_BINOP) +GTNODE(LE , GenTreeOp ,0,0,GTK_BINOP) +GTNODE(GE , GenTreeOp ,0,0,GTK_BINOP) +GTNODE(GT , GenTreeOp ,0,0,GTK_BINOP) // These implement EQ/NE(AND(x, y), 0). They always produce a value (GT_TEST is the version that does not). -GTNODE(TEST_EQ , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) -GTNODE(TEST_NE , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) +GTNODE(TEST_EQ , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) +GTNODE(TEST_NE , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) #ifdef TARGET_XARCH // BITTEST_EQ/NE(a, n) == EQ/NE(AND(a, LSH(1, n)), 0), but only used in xarch that has the BT instruction -GTNODE(BITTEST_EQ , GenTreeOp ,0,(GTK_BINOP|DBK_NOTHIR)) -GTNODE(BITTEST_NE , GenTreeOp ,0,(GTK_BINOP|DBK_NOTHIR)) +GTNODE(BITTEST_EQ , GenTreeOp ,0,0,(GTK_BINOP|DBK_NOTHIR)) +GTNODE(BITTEST_NE , GenTreeOp ,0,0,(GTK_BINOP|DBK_NOTHIR)) #endif // Conditional select with 3 operands: condition, true value, false value -GTNODE(SELECT , GenTreeConditional ,0,GTK_SPECIAL) +GTNODE(SELECT , GenTreeConditional ,0,0,GTK_SPECIAL) -GTNODE(COMMA , GenTreeOp ,0,GTK_BINOP|DBK_NOTLIR) -GTNODE(QMARK , GenTreeQmark ,0,GTK_BINOP|GTK_EXOP|DBK_NOTLIR) -GTNODE(COLON , GenTreeColon ,0,GTK_BINOP|DBK_NOTLIR) +GTNODE(COMMA , GenTreeOp ,0,1,GTK_BINOP|DBK_NOTLIR) +GTNODE(QMARK , GenTreeQmark ,0,1,GTK_BINOP|GTK_EXOP|DBK_NOTLIR) +GTNODE(COLON , GenTreeColon ,0,1,GTK_BINOP|DBK_NOTLIR) -GTNODE(INDEX_ADDR , GenTreeIndexAddr ,0,GTK_BINOP|GTK_EXOP) // Address of SZ-array-element. -GTNODE(MKREFANY , GenTreeOp ,0,GTK_BINOP|DBK_NOTLIR) -GTNODE(LEA , GenTreeAddrMode ,0,GTK_BINOP|GTK_EXOP|DBK_NOTHIR) +GTNODE(INDEX_ADDR , GenTreeIndexAddr ,0,0,GTK_BINOP|GTK_EXOP) // Address of SZ-array-element. +GTNODE(MKREFANY , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTLIR) +GTNODE(LEA , GenTreeAddrMode ,0,0,GTK_BINOP|GTK_EXOP|DBK_NOTHIR) #if !defined(TARGET_64BIT) // A GT_LONG node simply represents the long value produced by the concatenation // of its two (lower and upper half) operands. Some GT_LONG nodes are transient, // during the decomposing of longs; others are handled by codegen as operands of // nodes such as calls, returns and stores of long lclVars. -GTNODE(LONG , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) +GTNODE(LONG , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) // The following are nodes representing x86/arm32 specific long operators, including // high operators of a 64-bit operations that requires a carry/borrow, which are // named GT_XXX_HI for consistency, low operators of 64-bit operations that need // to not be modified in phases post-decompose, and operators that return 64-bit // results in one instruction. -GTNODE(ADD_LO , GenTreeOp ,1,GTK_BINOP|DBK_NOTHIR) -GTNODE(ADD_HI , GenTreeOp ,1,GTK_BINOP|DBK_NOTHIR) -GTNODE(SUB_LO , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) -GTNODE(SUB_HI , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) +GTNODE(ADD_LO , GenTreeOp ,1,0,GTK_BINOP|DBK_NOTHIR) +GTNODE(ADD_HI , GenTreeOp ,1,0,GTK_BINOP|DBK_NOTHIR) +GTNODE(SUB_LO , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) +GTNODE(SUB_HI , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) // The following are nodes that specify shifts that take a GT_LONG op1. The GT_LONG // contains the hi and lo parts of three operand shift form where one op will be @@ -177,13 +178,13 @@ GTNODE(SUB_HI , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) // will shift the lo bits of the high operand into the lo operand). LSH_HI // represents the high operation of a 64-bit left shift by a constant int, and // RSH_LO represents the lo operation of a 64-bit right shift by a constant int. -GTNODE(LSH_HI , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) -GTNODE(RSH_LO , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) +GTNODE(LSH_HI , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) +GTNODE(RSH_LO , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) #endif // !defined(TARGET_64BIT) #ifdef FEATURE_HW_INTRINSICS -GTNODE(HWINTRINSIC , GenTreeHWIntrinsic ,0,GTK_SPECIAL) // hardware intrinsics +GTNODE(HWINTRINSIC , GenTreeHWIntrinsic ,0,0,GTK_SPECIAL) // hardware intrinsics #endif // FEATURE_HW_INTRINSICS //----------------------------------------------------------------------------- @@ -191,13 +192,13 @@ GTNODE(HWINTRINSIC , GenTreeHWIntrinsic ,0,GTK_SPECIAL) // ha //----------------------------------------------------------------------------- // Saturating increment, used in division by a constant (LowerUnsignedDivOrMod). -GTNODE(INC_SATURATE , GenTreeOp ,0,GTK_UNOP|DBK_NOTHIR) +GTNODE(INC_SATURATE , GenTreeOp ,0,0,GTK_UNOP|DBK_NOTHIR) // Returns high bits (top N bits of the 2N bit result of an NxN multiply) // GT_MULHI is used in division by a constant (LowerUnsignedDivOrMod). We turn // the div into a MULHI + some adjustments. In codegen, we only use the // results of the high register, and we drop the low results. -GTNODE(MULHI , GenTreeOp ,1,GTK_BINOP|DBK_NOTHIR) +GTNODE(MULHI , GenTreeOp ,1,0,GTK_BINOP|DBK_NOTHIR) // A mul that returns the 2N bit result of an NxN multiply. This op is used for // multiplies that take two ints and return a long result. For 32 bit targets, @@ -206,15 +207,15 @@ GTNODE(MULHI , GenTreeOp ,1,GTK_BINOP|DBK_NOTHIR) // part of the result, whereas GT_MUL_LONG keeps both parts of the result. // MUL_LONG is also used on ARM64, where 64 bit multiplication is more expensive. #if !defined(TARGET_64BIT) -GTNODE(MUL_LONG , GenTreeMultiRegOp ,1,GTK_BINOP|DBK_NOTHIR) +GTNODE(MUL_LONG , GenTreeMultiRegOp ,1,0,GTK_BINOP|DBK_NOTHIR) #elif defined(TARGET_ARM64) -GTNODE(MUL_LONG , GenTreeOp ,1,GTK_BINOP|DBK_NOTHIR) +GTNODE(MUL_LONG , GenTreeOp ,1,0,GTK_BINOP|DBK_NOTHIR) #endif // AndNot - emitted on ARM/ARM64 as the BIC instruction. Also used for creating AndNot HWINTRINSIC vector nodes in a cross-ISA manner. -GTNODE(AND_NOT , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) +GTNODE(AND_NOT , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) #ifdef TARGET_ARM64 -GTNODE(BFIZ , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) // Bitfield Insert in Zero. +GTNODE(BFIZ , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) // Bitfield Insert in Zero. #endif //----------------------------------------------------------------------------- @@ -222,102 +223,102 @@ GTNODE(BFIZ , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) // Bitfiel //----------------------------------------------------------------------------- // Sets the condition flags according to the compare result. N.B. Not a relop, it does not produce a value and it cannot be reversed. -GTNODE(CMP , GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) +GTNODE(CMP , GenTreeOp ,0,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) // Generate a test instruction; sets the CPU flags according to (a & b) and does not produce a value. -GTNODE(TEST , GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) +GTNODE(TEST , GenTreeOp ,0,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) #ifdef TARGET_XARCH // The XARCH BT instruction. Like CMP, this sets the condition flags (CF to be precise) and does not produce a value. -GTNODE(BT , GenTreeOp ,0,(GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR)) +GTNODE(BT , GenTreeOp ,0,0,(GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR)) #endif // Makes a comparison and jumps if the condition specified by gtCondition is true. Does not set flags. -GTNODE(JCMP , GenTreeOpCC ,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) +GTNODE(JCMP , GenTreeOpCC ,0,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) // Do a bit test and jump if set/not set. -GTNODE(JTEST , GenTreeOpCC ,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) +GTNODE(JTEST , GenTreeOpCC ,0,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) // Checks the condition flags and branch if the condition specified by GenTreeCC::gtCondition is true. -GTNODE(JCC , GenTreeCC ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) +GTNODE(JCC , GenTreeCC ,0,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // Checks the condition flags and produces 1 if the condition specified by GenTreeCC::gtCondition is true and 0 otherwise. -GTNODE(SETCC , GenTreeCC ,0,GTK_LEAF|DBK_NOTHIR) +GTNODE(SETCC , GenTreeCC ,0,0,GTK_LEAF|DBK_NOTHIR) // Variant of SELECT that reuses flags computed by a previous node with the specified condition. -GTNODE(SELECTCC , GenTreeOpCC ,0,GTK_BINOP|DBK_NOTHIR) +GTNODE(SELECTCC , GenTreeOpCC ,0,0,GTK_BINOP|DBK_NOTHIR) #ifdef TARGET_ARM64 // The arm64 ccmp instruction. If the specified condition is true, compares two // operands and sets the condition flags according to the result. Otherwise // sets the condition flags to the specified immediate value. -GTNODE(CCMP , GenTreeCCMP ,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) +GTNODE(CCMP , GenTreeCCMP ,0,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) // Maps to arm64 csinc/cinc instruction. Computes result = condition ? op1 : op2 + 1. // If op2 is null, computes result = condition ? op1 + 1 : op1. -GTNODE(SELECT_INC , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) +GTNODE(SELECT_INC , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) // Variant of SELECT_INC that reuses flags computed by a previous node with the specified condition. -GTNODE(SELECT_INCCC , GenTreeOpCC ,0,GTK_BINOP|DBK_NOTHIR) +GTNODE(SELECT_INCCC , GenTreeOpCC ,0,0,GTK_BINOP|DBK_NOTHIR) // Maps to arm64 csinv/cinv instruction. Computes result = condition ? op1 : ~op2. // If op2 is null, computes result = condition ? ~op1 : op1. -GTNODE(SELECT_INV , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) +GTNODE(SELECT_INV , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) // Variant of SELECT_INV that reuses flags computed by a previous node with the specified condition. -GTNODE(SELECT_INVCC , GenTreeOpCC ,0,GTK_BINOP|DBK_NOTHIR) +GTNODE(SELECT_INVCC , GenTreeOpCC ,0,0,GTK_BINOP|DBK_NOTHIR) // Maps to arm64 csneg/cneg instruction.. Computes result = condition ? op1 : -op2. // If op2 is null, computes result = condition ? -op1 : op1. -GTNODE(SELECT_NEG , GenTreeOp ,0,GTK_BINOP|DBK_NOTHIR) +GTNODE(SELECT_NEG , GenTreeOp ,0,0,GTK_BINOP|DBK_NOTHIR) // Variant of SELECT_NEG that reuses flags computed by a previous node with the specified condition. -GTNODE(SELECT_NEGCC , GenTreeOpCC ,0,GTK_BINOP|DBK_NOTHIR) +GTNODE(SELECT_NEGCC , GenTreeOpCC ,0,0,GTK_BINOP|DBK_NOTHIR) #endif //----------------------------------------------------------------------------- // Other nodes that look like unary/binary operators: //----------------------------------------------------------------------------- -GTNODE(JTRUE , GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE) +GTNODE(JTRUE , GenTreeOp ,0,1,GTK_UNOP|GTK_NOVALUE) //----------------------------------------------------------------------------- // Other nodes that have special structure: //----------------------------------------------------------------------------- -GTNODE(ARR_ELEM , GenTreeArrElem ,0,GTK_SPECIAL) // Multi-dimensional array-element address -GTNODE(CALL , GenTreeCall ,0,GTK_SPECIAL|DBK_NOCONTAIN) -GTNODE(FIELD_LIST , GenTreeFieldList ,0,GTK_SPECIAL) // List of fields of a struct, when passed as an argument +GTNODE(ARR_ELEM , GenTreeArrElem ,0,0,GTK_SPECIAL) // Multi-dimensional array-element address +GTNODE(CALL , GenTreeCall ,0,0,GTK_SPECIAL|DBK_NOCONTAIN) +GTNODE(FIELD_LIST , GenTreeFieldList ,0,0,GTK_SPECIAL) // List of fields of a struct, when passed as an argument -GTNODE(RETURN , GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE) -GTNODE(SWITCH , GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE) -GTNODE(NO_OP , GenTree ,0,GTK_LEAF|GTK_NOVALUE) // A NOP that cannot be deleted. +GTNODE(RETURN , GenTreeOp ,0,1,GTK_UNOP|GTK_NOVALUE) +GTNODE(SWITCH , GenTreeOp ,0,1,GTK_UNOP|GTK_NOVALUE) +GTNODE(NO_OP , GenTree ,0,0,GTK_LEAF|GTK_NOVALUE) // A NOP that cannot be deleted. -GTNODE(START_NONGC , GenTree ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // Starts a new instruction group that will be non-gc interruptible. -GTNODE(START_PREEMPTGC , GenTree ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // Starts a new instruction group where preemptive GC is enabled. -GTNODE(PROF_HOOK , GenTree ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // Profiler Enter/Leave/TailCall hook. +GTNODE(START_NONGC , GenTree ,0,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // Starts a new instruction group that will be non-gc interruptible. +GTNODE(START_PREEMPTGC , GenTree ,0,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // Starts a new instruction group where preemptive GC is enabled. +GTNODE(PROF_HOOK , GenTree ,0,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // Profiler Enter/Leave/TailCall hook. -GTNODE(RETFILT , GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE) // End filter with TYP_I_IMPL return value. +GTNODE(RETFILT , GenTreeOp ,0,1,GTK_UNOP|GTK_NOVALUE) // End filter with TYP_I_IMPL return value. #if !defined(FEATURE_EH_FUNCLETS) -GTNODE(END_LFIN , GenTreeVal ,0,GTK_LEAF|GTK_NOVALUE) // End locally-invoked finally. +GTNODE(END_LFIN , GenTreeVal ,0,0,GTK_LEAF|GTK_NOVALUE) // End locally-invoked finally. #endif // !FEATURE_EH_FUNCLETS //----------------------------------------------------------------------------- // Nodes used by Lower to generate a closer CPU representation of other nodes //----------------------------------------------------------------------------- -GTNODE(JMPTABLE , GenTree ,0,GTK_LEAF|DBK_NOCONTAIN|DBK_NOTHIR) // Generates the jump table for switches -GTNODE(SWITCH_TABLE , GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) // Jump Table based switch construct +GTNODE(JMPTABLE , GenTree ,0,0,GTK_LEAF|DBK_NOCONTAIN|DBK_NOTHIR) // Generates the jump table for switches +GTNODE(SWITCH_TABLE , GenTreeOp ,0,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) // Jump Table based switch construct //----------------------------------------------------------------------------- // Nodes used only within the code generator: //----------------------------------------------------------------------------- -GTNODE(CLS_VAR_ADDR , GenTreeClsVar ,0,GTK_LEAF|DBK_NOTHIR) // static data member address -GTNODE(PHYSREG , GenTreePhysReg ,0,GTK_LEAF|DBK_NOTHIR) // read from a physical register -GTNODE(EMITNOP , GenTree ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // emitter-placed nop -GTNODE(PINVOKE_PROLOG , GenTree ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // pinvoke prolog seq -GTNODE(PINVOKE_EPILOG , GenTree ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // pinvoke epilog seq -GTNODE(RETURNTRAP , GenTreeOp ,0,GTK_UNOP|GTK_NOVALUE|DBK_NOTHIR) // a conditional call to wait on gc +GTNODE(CLS_VAR_ADDR , GenTreeClsVar ,0,0,GTK_LEAF|DBK_NOTHIR) // static data member address +GTNODE(PHYSREG , GenTreePhysReg ,0,0,GTK_LEAF|DBK_NOTHIR) // read from a physical register +GTNODE(EMITNOP , GenTree ,0,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // emitter-placed nop +GTNODE(PINVOKE_PROLOG , GenTree ,0,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // pinvoke prolog seq +GTNODE(PINVOKE_EPILOG , GenTree ,0,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // pinvoke epilog seq +GTNODE(RETURNTRAP , GenTreeOp ,0,0,GTK_UNOP|GTK_NOVALUE|DBK_NOTHIR) // a conditional call to wait on gc #if defined(TARGET_ARM) -GTNODE(PUTARG_REG , GenTreeMultiRegOp ,0,GTK_UNOP|DBK_NOTHIR) // operator that places outgoing arg in register +GTNODE(PUTARG_REG , GenTreeMultiRegOp ,0,0,GTK_UNOP|DBK_NOTHIR) // operator that places outgoing arg in register #else -GTNODE(PUTARG_REG , GenTreeOp ,0,GTK_UNOP|DBK_NOTHIR) // operator that places outgoing arg in register +GTNODE(PUTARG_REG , GenTreeOp ,0,0,GTK_UNOP|DBK_NOTHIR) // operator that places outgoing arg in register #endif -GTNODE(PUTARG_STK , GenTreePutArgStk ,0,GTK_UNOP|GTK_NOVALUE|DBK_NOTHIR) // operator that places outgoing arg in stack +GTNODE(PUTARG_STK , GenTreePutArgStk ,0,0,GTK_UNOP|GTK_NOVALUE|DBK_NOTHIR) // operator that places outgoing arg in stack #if FEATURE_ARG_SPLIT -GTNODE(PUTARG_SPLIT , GenTreePutArgSplit ,0,GTK_UNOP|DBK_NOTHIR) // operator that places outgoing arg in registers with stack (split struct in ARM32) +GTNODE(PUTARG_SPLIT , GenTreePutArgSplit ,0,0,GTK_UNOP|DBK_NOTHIR) // operator that places outgoing arg in registers with stack (split struct in ARM32) #endif // FEATURE_ARG_SPLIT -GTNODE(SWAP , GenTreeOp ,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) // op1 and op2 swap (registers) -GTNODE(COPY , GenTreeCopyOrReload,0,GTK_UNOP|DBK_NOTHIR) // Copies a variable from its current location to a register that satisfies -GTNODE(RELOAD , GenTreeCopyOrReload,0,GTK_UNOP|DBK_NOTHIR) // code generation constraints. The operand is the actual lclVar node. -GTNODE(IL_OFFSET , GenTreeILOffset ,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // marks an IL offset for debugging purposes +GTNODE(SWAP , GenTreeOp ,0,0,GTK_BINOP|GTK_NOVALUE|DBK_NOTHIR) // op1 and op2 swap (registers) +GTNODE(COPY , GenTreeCopyOrReload,0,0,GTK_UNOP|DBK_NOTHIR) // Copies a variable from its current location to a register that satisfies +GTNODE(RELOAD , GenTreeCopyOrReload,0,0,GTK_UNOP|DBK_NOTHIR) // code generation constraints. The operand is the actual lclVar node. +GTNODE(IL_OFFSET , GenTreeILOffset ,0,0,GTK_LEAF|GTK_NOVALUE|DBK_NOTHIR) // marks an IL offset for debugging purposes /*****************************************************************************/ #undef GTNODE diff --git a/src/coreclr/jit/hwintrinsic.cpp b/src/coreclr/jit/hwintrinsic.cpp index 35d1b6aa249bd5..0b3c1ec052bd00 100644 --- a/src/coreclr/jit/hwintrinsic.cpp +++ b/src/coreclr/jit/hwintrinsic.cpp @@ -9,7 +9,7 @@ static const HWIntrinsicInfo hwIntrinsicInfoArray[] = { // clang-format off #if defined(TARGET_XARCH) -#define HARDWARE_INTRINSIC(isa, name, size, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \ +#define HARDWARE_INTRINSIC(isa, name, size, numarg, extra, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \ { \ /* name */ #name, \ /* flags */ static_cast(flag), \ @@ -22,7 +22,7 @@ static const HWIntrinsicInfo hwIntrinsicInfoArray[] = { }, #include "hwintrinsiclistxarch.h" #elif defined (TARGET_ARM64) -#define HARDWARE_INTRINSIC(isa, name, size, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \ +#define HARDWARE_INTRINSIC(isa, name, size, numarg, extra, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \ { \ /* name */ #name, \ /* flags */ static_cast(flag), \ @@ -495,9 +495,9 @@ NamedIntrinsic HWIntrinsicInfo::lookupId(Compiler* comp, return NI_Illegal; } - bool isIsaSupported = comp->compSupportsHWIntrinsic(isa); - + bool isIsaSupported = comp->compSupportsHWIntrinsic(isa); bool isHardwareAcceleratedProp = (strcmp(methodName, "get_IsHardwareAccelerated") == 0); + #ifdef TARGET_XARCH if (isHardwareAcceleratedProp) { @@ -541,22 +541,22 @@ NamedIntrinsic HWIntrinsicInfo::lookupId(Compiler* comp, // // When the target hardware does support the instruction set, we can return a // constant true. When it doesn't then we want to report the check as dynamically - // supported instead. This allows some targets, such as AOT, to emit a check against - // a cached CPU query so lightup can still happen (such as for SSE4.1 when the target - // hardware is SSE2). + // supported instead if the opportunistic support does exist. This allows some targets, + // such as AOT, to emit a check against a cached CPU query so lightup can still happen + // (such as for SSE4.1 when the target hardware is SSE2). // // When the compiler doesn't support ISA or when it does but the target hardware does // not and we aren't in a scenario with support for a dynamic check, we want to return false. - if (isIsaSupported) + if (isIsaSupported && comp->compSupportsHWIntrinsic(isa)) { - if (comp->compExactlyDependsOn(isa)) + if (!comp->IsTargetAbi(CORINFO_NATIVEAOT_ABI) || comp->compExactlyDependsOn(isa)) { return NI_IsSupported_True; } - - if (comp->IsTargetAbi(CORINFO_NATIVEAOT_ABI)) + else { + assert(comp->IsTargetAbi(CORINFO_NATIVEAOT_ABI)); return NI_IsSupported_Dynamic; } } diff --git a/src/coreclr/jit/hwintrinsic.h b/src/coreclr/jit/hwintrinsic.h index 26599ba5b1de25..01b886744ea4f7 100644 --- a/src/coreclr/jit/hwintrinsic.h +++ b/src/coreclr/jit/hwintrinsic.h @@ -201,6 +201,8 @@ enum HWIntrinsicFlag : unsigned int // The intrinsic is a PermuteVar2x intrinsic HW_Flag_PermuteVar2x = 0x4000000, #endif // TARGET_XARCH + // The intrinsic is an embedded broadcast compatiable intrinsic + HW_Flag_EmbBroadcastCompatible = 0x8000000, }; #if defined(TARGET_XARCH) @@ -328,6 +330,25 @@ enum class FloatRoundingMode : uint8_t NoException = 0x08, }; +enum class IntComparisonMode : uint8_t +{ + Equal = 0, + LessThan = 1, + LessThanOrEqual = 2, + False = 3, + + NotEqual = 4, + GreaterThanOrEqual = 5, + GreaterThan = 6, + True = 7, + + NotGreaterThanOrEqual = LessThan, + NotGreaterThan = LessThanOrEqual, + + NotLessThan = GreaterThanOrEqual, + NotLessThanOrEqual = GreaterThan +}; + enum class TernaryLogicUseFlags : uint8_t { // Indicates no flags are present @@ -491,217 +512,7 @@ struct HWIntrinsicInfo } #ifdef TARGET_XARCH - static int lookupIval(NamedIntrinsic id, bool opportunisticallyDependsOnAVX) - { - switch (id) - { - case NI_SSE_CompareEqual: - case NI_SSE_CompareScalarEqual: - case NI_SSE2_CompareEqual: - case NI_SSE2_CompareScalarEqual: - case NI_AVX_CompareEqual: - { - return static_cast(FloatComparisonMode::OrderedEqualNonSignaling); - } - - case NI_SSE_CompareGreaterThan: - case NI_SSE_CompareScalarGreaterThan: - case NI_SSE2_CompareGreaterThan: - case NI_SSE2_CompareScalarGreaterThan: - case NI_AVX_CompareGreaterThan: - { - if (opportunisticallyDependsOnAVX) - { - 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. - - assert(id != NI_AVX_CompareGreaterThan); - return static_cast(FloatComparisonMode::OrderedLessThanSignaling); - } - - case NI_SSE_CompareLessThan: - case NI_SSE_CompareScalarLessThan: - case NI_SSE2_CompareLessThan: - case NI_SSE2_CompareScalarLessThan: - case NI_AVX_CompareLessThan: - { - return static_cast(FloatComparisonMode::OrderedLessThanSignaling); - } - - case NI_SSE_CompareGreaterThanOrEqual: - case NI_SSE_CompareScalarGreaterThanOrEqual: - case NI_SSE2_CompareGreaterThanOrEqual: - case NI_SSE2_CompareScalarGreaterThanOrEqual: - case NI_AVX_CompareGreaterThanOrEqual: - { - if (opportunisticallyDependsOnAVX) - { - 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. - - assert(id != NI_AVX_CompareGreaterThanOrEqual); - return static_cast(FloatComparisonMode::OrderedLessThanOrEqualSignaling); - } - - case NI_SSE_CompareLessThanOrEqual: - case NI_SSE_CompareScalarLessThanOrEqual: - case NI_SSE2_CompareLessThanOrEqual: - case NI_SSE2_CompareScalarLessThanOrEqual: - case NI_AVX_CompareLessThanOrEqual: - { - return static_cast(FloatComparisonMode::OrderedLessThanOrEqualSignaling); - } - - case NI_SSE_CompareNotEqual: - case NI_SSE_CompareScalarNotEqual: - case NI_SSE2_CompareNotEqual: - case NI_SSE2_CompareScalarNotEqual: - case NI_AVX_CompareNotEqual: - { - return static_cast(FloatComparisonMode::UnorderedNotEqualNonSignaling); - } - - case NI_SSE_CompareNotGreaterThan: - case NI_SSE_CompareScalarNotGreaterThan: - case NI_SSE2_CompareNotGreaterThan: - case NI_SSE2_CompareScalarNotGreaterThan: - case NI_AVX_CompareNotGreaterThan: - { - if (opportunisticallyDependsOnAVX) - { - 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. - - assert(id != NI_AVX_CompareNotGreaterThan); - return static_cast(FloatComparisonMode::UnorderedNotLessThanSignaling); - } - - case NI_SSE_CompareNotLessThan: - case NI_SSE_CompareScalarNotLessThan: - case NI_SSE2_CompareNotLessThan: - case NI_SSE2_CompareScalarNotLessThan: - case NI_AVX_CompareNotLessThan: - { - return static_cast(FloatComparisonMode::UnorderedNotLessThanSignaling); - } - - case NI_SSE_CompareNotGreaterThanOrEqual: - case NI_SSE_CompareScalarNotGreaterThanOrEqual: - case NI_SSE2_CompareNotGreaterThanOrEqual: - case NI_SSE2_CompareScalarNotGreaterThanOrEqual: - case NI_AVX_CompareNotGreaterThanOrEqual: - { - if (opportunisticallyDependsOnAVX) - { - 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. - - assert(id != NI_AVX_CompareNotGreaterThanOrEqual); - return static_cast(FloatComparisonMode::UnorderedNotLessThanOrEqualSignaling); - } - - case NI_SSE_CompareNotLessThanOrEqual: - case NI_SSE_CompareScalarNotLessThanOrEqual: - case NI_SSE2_CompareNotLessThanOrEqual: - case NI_SSE2_CompareScalarNotLessThanOrEqual: - case NI_AVX_CompareNotLessThanOrEqual: - { - return static_cast(FloatComparisonMode::UnorderedNotLessThanOrEqualSignaling); - } - - case NI_SSE_CompareOrdered: - case NI_SSE_CompareScalarOrdered: - case NI_SSE2_CompareOrdered: - case NI_SSE2_CompareScalarOrdered: - case NI_AVX_CompareOrdered: - { - return static_cast(FloatComparisonMode::OrderedNonSignaling); - } - - case NI_SSE_CompareUnordered: - case NI_SSE_CompareScalarUnordered: - case NI_SSE2_CompareUnordered: - case NI_SSE2_CompareScalarUnordered: - case NI_AVX_CompareUnordered: - { - return static_cast(FloatComparisonMode::UnorderedNonSignaling); - } - - case NI_SSE41_Ceiling: - case NI_SSE41_CeilingScalar: - case NI_AVX_Ceiling: - { - FALLTHROUGH; - } - - case NI_SSE41_RoundToPositiveInfinity: - case NI_SSE41_RoundToPositiveInfinityScalar: - case NI_AVX_RoundToPositiveInfinity: - { - return static_cast(FloatRoundingMode::ToPositiveInfinity); - } - - case NI_SSE41_Floor: - case NI_SSE41_FloorScalar: - case NI_AVX_Floor: - { - FALLTHROUGH; - } - - case NI_SSE41_RoundToNegativeInfinity: - case NI_SSE41_RoundToNegativeInfinityScalar: - case NI_AVX_RoundToNegativeInfinity: - { - return static_cast(FloatRoundingMode::ToNegativeInfinity); - } - - case NI_SSE41_RoundCurrentDirection: - case NI_SSE41_RoundCurrentDirectionScalar: - case NI_AVX_RoundCurrentDirection: - { - return static_cast(FloatRoundingMode::CurrentDirection); - } - - case NI_SSE41_RoundToNearestInteger: - case NI_SSE41_RoundToNearestIntegerScalar: - case NI_AVX_RoundToNearestInteger: - { - return static_cast(FloatRoundingMode::ToNearestInteger); - } - - case NI_SSE41_RoundToZero: - case NI_SSE41_RoundToZeroScalar: - case NI_AVX_RoundToZero: - { - return static_cast(FloatRoundingMode::ToZero); - } - - default: - { - return -1; - } - } - } + static int lookupIval(Compiler* comp, NamedIntrinsic id, var_types simdBaseType); #endif static bool tryLookupSimdSize(NamedIntrinsic id, unsigned* pSimdSize) @@ -769,6 +580,12 @@ struct HWIntrinsicInfo return (flags & HW_Flag_Commutative) != 0; } + static bool IsEmbBroadcastCompatible(NamedIntrinsic id) + { + HWIntrinsicFlag flags = lookupFlags(id); + return (flags & HW_Flag_EmbBroadcastCompatible) != 0; + } + static bool IsMaybeCommutative(NamedIntrinsic id) { HWIntrinsicFlag flags = lookupFlags(id); diff --git a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp index 973d4176a00b63..7570765fcdadd9 100644 --- a/src/coreclr/jit/hwintrinsiccodegenxarch.cpp +++ b/src/coreclr/jit/hwintrinsiccodegenxarch.cpp @@ -97,9 +97,6 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) // We need to validate that other phases of the compiler haven't introduced unsupported intrinsics assert(compiler->compIsaSupportedDebugOnly(isa)); - - int ival = HWIntrinsicInfo::lookupIval(intrinsicId, compiler->compOpportunisticallyDependsOn(InstructionSet_AVX)); - assert(HWIntrinsicInfo::RequiresCodegen(intrinsicId)); if (genIsTableDrivenHWIntrinsic(intrinsicId, category)) @@ -119,12 +116,15 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) emitter* emit = GetEmitter(); assert(numArgs >= 0); + instruction ins = HWIntrinsicInfo::lookupIns(intrinsicId, baseType); assert(ins != INS_invalid); - emitAttr simdSize = emitActualTypeSize(Compiler::getSIMDTypeForSize(node->GetSimdSize())); + emitAttr simdSize = emitActualTypeSize(Compiler::getSIMDTypeForSize(node->GetSimdSize())); assert(simdSize != 0); + int ival = HWIntrinsicInfo::lookupIval(compiler, intrinsicId, baseType); + switch (numArgs) { case 1: @@ -144,7 +144,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) genConsumeRegs(op1); op1Reg = op1->GetRegNum(); - if ((ival != -1) && varTypeIsFloating(baseType)) + if (ival != -1) { assert((ival >= 0) && (ival <= 127)); if (HWIntrinsicInfo::CopiesUpperBits(intrinsicId)) @@ -208,7 +208,7 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) op1Reg = targetReg; } - if ((ival != -1) && varTypeIsFloating(baseType)) + if (ival != -1) { assert((ival >= 0) && (ival <= 127)); genHWIntrinsic_R_R_RM_I(node, ins, simdSize, static_cast(ival)); @@ -235,7 +235,6 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) } else if (HWIntrinsicInfo::isImmOp(intrinsicId, op2)) { - assert(ival == -1); auto emitSwCase = [&](int8_t i) { if (HWIntrinsicInfo::CopiesUpperBits(intrinsicId)) { @@ -293,10 +292,10 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) genConsumeRegs(op3); op3Reg = op3->GetRegNum(); + assert(ival == -1); + if (HWIntrinsicInfo::isImmOp(intrinsicId, op3)) { - assert(ival == -1); - auto emitSwCase = [&](int8_t i) { genHWIntrinsic_R_R_RM_I(node, ins, simdSize, i); }; if (op3->IsCnsIntOrI()) @@ -384,10 +383,10 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) genConsumeRegs(op4); op4Reg = op4->GetRegNum(); + assert(ival == -1); + if (HWIntrinsicInfo::isImmOp(intrinsicId, op4)) { - assert(ival == -1); - auto emitSwCase = [&](int8_t i) { genHWIntrinsic_R_R_R_RM_I(node, ins, simdSize, i); }; if (op4->IsCnsIntOrI()) @@ -455,6 +454,8 @@ void CodeGen::genHWIntrinsic(GenTreeHWIntrinsic* node) case InstructionSet_AVX512F_X64: case InstructionSet_AVX512BW: case InstructionSet_AVX512BW_VL: + case InstructionSet_AVX512VBMI: + case InstructionSet_AVX512VBMI_VL: genAvxFamilyIntrinsic(node); break; case InstructionSet_AES: @@ -1913,6 +1914,7 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node) instruction maskIns; instruction kmovIns; + emitAttr kmovAttr = EA_4BYTE; // TODO-XARCH-AVX512 note that this type/kmov combination assumes 512-bit vector types but would change // if used for other vector lengths, i.e., TYPE_BYTE requires kmovq for for 512-bit vector, but kmovd @@ -1921,130 +1923,78 @@ void CodeGen::genAvxFamilyIntrinsic(GenTreeHWIntrinsic* node) { case TYP_BYTE: case TYP_UBYTE: - maskIns = INS_vpmovb2m; - kmovIns = INS_kmovq_gpr; + { + maskIns = INS_vpmovb2m; + kmovIns = INS_kmovq_gpr; + kmovAttr = EA_8BYTE; break; + } + case TYP_SHORT: case TYP_USHORT: + { maskIns = INS_vpmovw2m; kmovIns = INS_kmovd_gpr; break; + } + case TYP_INT: case TYP_UINT: case TYP_FLOAT: + { maskIns = INS_vpmovd2m; kmovIns = INS_kmovw_gpr; break; + } + case TYP_DOUBLE: case TYP_LONG: case TYP_ULONG: + { maskIns = INS_vpmovq2m; kmovIns = INS_kmovb_gpr; break; + } + default: + { unreached(); + } } assert(emitter::isMaskReg(maskReg)); emit->emitIns_R_R(maskIns, attr, maskReg, op1Reg); - emit->emitIns_Mov(kmovIns, EA_8BYTE, targetReg, maskReg, INS_FLAGS_DONT_CARE); - break; - } - - case NI_AVX512F_CompareEqualSpecial: - { - GenTree* op2 = node->Op(2); - op1Reg = op1->GetRegNum(); - regNumber op2Reg = op2->GetRegNum(); - - instruction compareIns = HWIntrinsicInfo::lookupIns(NI_AVX512F_CompareEqualSpecial, baseType); - - assert(compareIns != INS_invalid); - assert(emitter::isMaskReg(targetReg)); - - emit->emitIns_R_R_R_I(compareIns, attr, targetReg, op1Reg, op2Reg, 0); + emit->emitIns_Mov(kmovIns, kmovAttr, targetReg, maskReg, INS_FLAGS_DONT_CARE); break; } - case NI_AVX512F_CompareGreaterThanOrEqualSpecial: - { - GenTree* op2 = node->Op(2); - op1Reg = op1->GetRegNum(); - regNumber op2Reg = op2->GetRegNum(); - - instruction compareIns = HWIntrinsicInfo::lookupIns(NI_AVX512F_CompareGreaterThanOrEqualSpecial, baseType); - - assert(compareIns != INS_invalid); - assert(emitter::isMaskReg(targetReg)); - - emit->emitIns_R_R_R_I(compareIns, attr, targetReg, op1Reg, op2Reg, 5); - break; - } - - case NI_AVX512F_CompareGreaterThanSpecial: - { - GenTree* op2 = node->Op(2); - op1Reg = op1->GetRegNum(); - regNumber op2Reg = op2->GetRegNum(); - - instruction compareIns = HWIntrinsicInfo::lookupIns(NI_AVX512F_CompareGreaterThanSpecial, baseType); - - assert(compareIns != INS_invalid); - assert(emitter::isMaskReg(targetReg)); - - emit->emitIns_R_R_R_I(compareIns, attr, targetReg, op1Reg, op2Reg, 6); - break; - } - - case NI_AVX512F_CompareLessThanOrEqualSpecial: - { - GenTree* op2 = node->Op(2); - op1Reg = op1->GetRegNum(); - regNumber op2Reg = op2->GetRegNum(); - - instruction compareIns = HWIntrinsicInfo::lookupIns(NI_AVX512F_CompareLessThanOrEqualSpecial, baseType); - - assert(compareIns != INS_invalid); - assert(emitter::isMaskReg(targetReg)); - - emit->emitIns_R_R_R_I(compareIns, attr, targetReg, op1Reg, op2Reg, 2); - break; - } - - case NI_AVX512F_CompareLessThanSpecial: - { - GenTree* op2 = node->Op(2); - op1Reg = op1->GetRegNum(); - regNumber op2Reg = op2->GetRegNum(); - - instruction compareIns = HWIntrinsicInfo::lookupIns(NI_AVX512F_CompareLessThanSpecial, baseType); - - assert(compareIns != INS_invalid); - assert(emitter::isMaskReg(targetReg)); - - emit->emitIns_R_R_R_I(compareIns, attr, targetReg, op1Reg, op2Reg, 1); - break; - } - - case NI_AVX512F_MoveMaskToVectorSpecial: + case NI_AVX512F_KORTEST: { op1Reg = op1->GetRegNum(); - instruction maskMovIns = HWIntrinsicInfo::lookupIns(NI_AVX512F_MoveMaskToVectorSpecial, baseType); + uint32_t simdSize = node->GetSimdSize(); + uint32_t count = simdSize / genTypeSize(baseType); - assert(maskMovIns != INS_invalid); - assert(emitter::isMaskReg(op1Reg)); + instruction testIns; - emit->emitIns_R_R(maskMovIns, attr, targetReg, op1Reg); - break; - } - - case NI_AVX512F_KORTEST: - { - op1Reg = op1->GetRegNum(); - - instruction testIns = HWIntrinsicInfo::lookupIns(NI_AVX512F_KORTEST, baseType); + if (count <= 8) + { + testIns = INS_kortestb; + } + else if (count == 16) + { + testIns = INS_kortestw; + } + else if (count == 32) + { + testIns = INS_kortestd; + } + else + { + assert(count == 64); + testIns = INS_kortestq; + } assert(testIns != INS_invalid); assert(emitter::isMaskReg(op1Reg)); diff --git a/src/coreclr/jit/hwintrinsiclistarm64.h b/src/coreclr/jit/hwintrinsiclistarm64.h index 2f1e4e03217133..97c9b66ad149b6 100644 --- a/src/coreclr/jit/hwintrinsiclistarm64.h +++ b/src/coreclr/jit/hwintrinsiclistarm64.h @@ -11,747 +11,747 @@ #ifdef FEATURE_HW_INTRINSICS // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size Number of arguments Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Vector64 Intrinsics -HARDWARE_INTRINSIC(Vector64, Abs, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Add, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, AndNot, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, As, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsByte, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsDouble, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsInt16, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsInt32, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsInt64, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsNInt, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsNUInt, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsSByte, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsSingle, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsUInt16, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsUInt32, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, AsUInt64, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, BitwiseAnd, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, BitwiseOr, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Ceiling, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, ConditionalSelect, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, ConvertToDouble, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector64, ConvertToInt32, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector64, ConvertToInt64, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector64, ConvertToSingle, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector64, ConvertToUInt32, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector64, ConvertToUInt64, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector64, Create, 8, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, CreateScalar, 8, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, CreateScalarUnsafe, 8, 1, {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, Divide, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Dot, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Equals, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, EqualsAll, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, EqualsAny, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, ExtractMostSignificantBits, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Floor, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, get_AllBitsSet, 8, 0, {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_One, 8, 0, {INS_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, {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, GetElement, 8, 2, {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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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_Equality, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(Vector64, op_ExclusiveOr, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, op_Inequality, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(Vector64, op_LeftShift, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, op_Multiply, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, op_OnesComplement, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, op_RightShift, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, op_Subtraction, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, op_UnaryNegation, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, op_UnaryPlus, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, op_UnsignedRightShift, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, ShiftLeft, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, ShiftRightArithmetic, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, ShiftRightLogical, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Shuffle, 8, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Sqrt, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Store, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, StoreAligned, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, StoreAlignedNonTemporal, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, StoreUnsafe, 8, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Subtract, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, Sum, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector64, ToScalar, 8, 1, {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, {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, {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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, WithElement, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector64, Xor, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) +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, 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, 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_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, 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, 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) +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_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) +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, 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, 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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size Number of arguments Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Vector128 Intrinsics -HARDWARE_INTRINSIC(Vector128, Abs, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Add, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AndNot, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, As, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsByte, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsDouble, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsInt16, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsInt32, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsNInt, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsNUInt, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsSByte, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsSingle, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsUInt16, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsUInt32, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsUInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsVector, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsVector2, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, AsVector3, 16, 1, {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, {INS_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, {INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, Create, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, CreateScalar, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, CreateScalarUnsafe, 16, 1, {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, Divide, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Dot, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Equals, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, EqualsAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, EqualsAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ExtractMostSignificantBits, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Floor, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, get_AllBitsSet, 16, 0, {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_One, 16, 0, {INS_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, {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, GetElement, 16, 2, {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, {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, {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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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_Equality, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(Vector128, op_ExclusiveOr, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_Inequality, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(Vector128, op_LeftShift, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_RightShift, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_UnsignedRightShift, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_Multiply, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_OnesComplement, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_Subtraction, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_UnaryNegation, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_UnaryPlus, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ShiftLeft, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ShiftRightArithmetic, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ShiftRightLogical, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Shuffle, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Sqrt, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Store, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, StoreAligned, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, StoreAlignedNonTemporal, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, StoreUnsafe, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Subtract, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Sum, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ToScalar, 16, 1, {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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, WithElement, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(Vector128, WithLower, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, WithUpper, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Xor, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|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_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, 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, 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, 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_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, 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, 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) +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_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) +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, 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, 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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size Number of arguments Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // AdvSimd Intrinsics -HARDWARE_INTRINSIC(AdvSimd, Abs, -1, 1, {INS_abs, INS_invalid, INS_abs, INS_invalid, INS_abs, INS_invalid, INS_invalid, INS_invalid, INS_fabs, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, AbsSaturate, -1, 1, {INS_sqabs, INS_invalid, INS_sqabs, INS_invalid, INS_sqabs, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, AbsScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fabs, INS_fabs}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, AbsoluteCompareGreaterThan, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, AbsoluteCompareGreaterThanOrEqual, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, AbsoluteCompareLessThan, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, AbsoluteCompareLessThanOrEqual, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifference, -1, 2, {INS_sabd, INS_uabd, INS_sabd, INS_uabd, INS_sabd, INS_uabd, INS_invalid, INS_invalid, INS_fabd, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifferenceAdd, -1, 3, {INS_saba, INS_uaba, INS_saba, INS_uaba, INS_saba, INS_uaba, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifferenceWideningLower, 8, 2, {INS_sabdl, INS_uabdl, INS_sabdl, INS_uabdl, INS_sabdl, INS_uabdl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifferenceWideningLowerAndAdd, 8, 3, {INS_sabal, INS_uabal, INS_sabal, INS_uabal, INS_sabal, INS_uabal, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifferenceWideningUpper, 16, 2, {INS_sabdl2, INS_uabdl2, INS_sabdl2, INS_uabdl2, INS_sabdl2, INS_uabdl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifferenceWideningUpperAndAdd, 16, 3, {INS_sabal2, INS_uabal2, INS_sabal2, INS_uabal2, INS_sabal2, INS_uabal2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, Add, -1, 2, {INS_add, INS_add, INS_add, INS_add, INS_add, INS_add, INS_add, INS_add, INS_fadd, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, AddHighNarrowingLower, 8, 2, {INS_addhn, INS_addhn, INS_addhn, INS_addhn, INS_addhn, INS_addhn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, AddHighNarrowingUpper, 16, 3, {INS_addhn2, INS_addhn2, INS_addhn2, INS_addhn2, INS_addhn2, INS_addhn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, AddPairwise, 8, 2, {INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_invalid, INS_invalid, INS_faddp, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, AddPairwiseWidening, -1, 1, {INS_saddlp, INS_uaddlp, INS_saddlp, INS_uaddlp, INS_saddlp, INS_uaddlp, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, AddPairwiseWideningAndAdd, -1, 2, {INS_sadalp, INS_uadalp, INS_sadalp, INS_uadalp, INS_sadalp, INS_uadalp, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, AddPairwiseWideningAndAddScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sadalp, INS_uadalp, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, AddPairwiseWideningScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_saddlp, INS_uaddlp, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, AddRoundedHighNarrowingLower, 8, 2, {INS_raddhn, INS_raddhn, INS_raddhn, INS_raddhn, INS_raddhn, INS_raddhn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, AddRoundedHighNarrowingUpper, 16, 3, {INS_raddhn2, INS_raddhn2, INS_raddhn2, INS_raddhn2, INS_raddhn2, INS_raddhn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, AddSaturate, -1, 2, {INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, AddSaturateScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqadd, INS_uqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, AddScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_add, INS_add, INS_fadd, INS_fadd}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, AddWideningLower, 8, 2, {INS_saddl, INS_uaddl, INS_saddl, INS_uaddl, INS_saddl, INS_uaddl, INS_saddw, INS_uaddw, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, AddWideningUpper, 16, 2, {INS_saddl2, INS_uaddl2, INS_saddl2, INS_uaddl2, INS_saddl2, INS_uaddl2, INS_saddw2, INS_uaddw2, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, And, -1, 2, {INS_and, INS_and, INS_and, INS_and, INS_and, INS_and, INS_and, INS_and, INS_and, INS_and}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, BitwiseClear, -1, 2, {INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, BitwiseSelect, -1, 3, {INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, Ceiling, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, CeilingScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_frintp}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, CompareEqual, -1, 2, {INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_invalid, INS_invalid, INS_fcmeq, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThanOrEqual, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SIMD, HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd, CompareLessThan, -1, 2, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, CompareLessThanOrEqual, -1, 2, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, CompareTest, -1, 2, {INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_invalid, INS_invalid, INS_cmtst, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, ConvertToInt32RoundAwayFromZero, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtas, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, ConvertToInt32RoundAwayFromZeroScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtas, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ConvertToInt32RoundToEven, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtns, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, ConvertToInt32RoundToEvenScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtns, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ConvertToInt32RoundToNegativeInfinity, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtms, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, ConvertToInt32RoundToNegativeInfinityScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtms, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ConvertToInt32RoundToPositiveInfinity, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtps, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, ConvertToInt32RoundToPositiveInfinityScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtps, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ConvertToInt32RoundToZero, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtzs, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, ConvertToInt32RoundToZeroScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtzs, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ConvertToSingle, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_scvtf, INS_ucvtf, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, ConvertToSingleScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_scvtf, INS_ucvtf, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ConvertToUInt32RoundAwayFromZero, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtau, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, ConvertToUInt32RoundAwayFromZeroScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtau, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ConvertToUInt32RoundToEven, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtnu, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, ConvertToUInt32RoundToEvenScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtnu, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ConvertToUInt32RoundToNegativeInfinity, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtmu, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, ConvertToUInt32RoundToNegativeInfinityScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtmu, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ConvertToUInt32RoundToPositiveInfinity, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtpu, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, ConvertToUInt32RoundToPositiveInfinityScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtpu, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ConvertToUInt32RoundToZero, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtzu, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, ConvertToUInt32RoundToZeroScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtzu, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, DivideScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fdiv, INS_fdiv}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, DuplicateSelectedScalarToVector64, -1, 2, {INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_invalid, INS_invalid, INS_dup, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, DuplicateSelectedScalarToVector128, -1, 2, {INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_invalid, INS_invalid, INS_dup, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, DuplicateToVector64, 8, 1, {INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_invalid, INS_invalid, INS_dup, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd, DuplicateToVector128, 16, 1, {INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_invalid, INS_invalid, INS_dup, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd, Extract, -1, 2, {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_HasImmediateOperand|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, ExtractNarrowingLower, 8, 1, {INS_xtn, INS_xtn, INS_xtn, INS_xtn, INS_xtn, INS_xtn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, ExtractNarrowingSaturateLower, 8, 1, {INS_sqxtn, INS_uqxtn, INS_sqxtn, INS_uqxtn, INS_sqxtn, INS_uqxtn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, ExtractNarrowingSaturateUnsignedLower, 8, 1, {INS_invalid, INS_sqxtun, INS_invalid, INS_sqxtun, INS_invalid, INS_sqxtun, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, ExtractNarrowingSaturateUnsignedUpper, 16, 2, {INS_invalid, INS_sqxtun2, INS_invalid, INS_sqxtun2, INS_invalid, INS_sqxtun2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, ExtractNarrowingSaturateUpper, 16, 2, {INS_sqxtn2, INS_uqxtn2, INS_sqxtn2, INS_uqxtn2, INS_sqxtn2, INS_uqxtn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, ExtractNarrowingUpper, 16, 2, {INS_xtn2, INS_xtn2, INS_xtn2, INS_xtn2, INS_xtn2, INS_xtn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, ExtractVector64, 8, 3, {INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_invalid, INS_invalid, INS_ext, INS_invalid}, HW_Category_SIMD, HW_Flag_HasImmediateOperand|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, ExtractVector128, 16, 3, {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_HasImmediateOperand|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, Floor, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintm, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, FloorScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintm, INS_frintm}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, FusedAddHalving, -1, 2, {INS_shadd, INS_uhadd, INS_shadd, INS_uhadd, INS_shadd, INS_uhadd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, FusedAddRoundedHalving, -1, 2, {INS_srhadd, INS_urhadd, INS_srhadd, INS_urhadd, INS_srhadd, INS_urhadd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, FusedMultiplyAdd, -1, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmla, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, FusedMultiplyAddScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmadd, INS_fmadd}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, FusedMultiplyAddNegatedScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fnmadd, INS_fnmadd}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, FusedMultiplySubtract, -1, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmls, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, FusedMultiplySubtractScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmsub, INS_fmsub}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, FusedMultiplySubtractNegatedScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fnmsub, INS_fnmsub}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, FusedSubtractHalving, -1, 2, {INS_shsub, INS_uhsub, INS_shsub, INS_uhsub, INS_shsub, INS_uhsub, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, Insert, -1, 3, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins}, HW_Category_SIMD, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd, InsertScalar, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ins, INS_ins, INS_invalid, INS_ins}, HW_Category_SIMD, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, LeadingSignCount, -1, 1, {INS_cls, INS_invalid, INS_cls, INS_invalid, INS_cls, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, LeadingZeroCount, -1, 1, {INS_clz, INS_clz, INS_clz, INS_clz, INS_clz, INS_clz, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, LoadAndInsertScalar, -1, 3, {INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1}, HW_Category_MemoryLoad, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, LoadAndReplicateToVector64, 8, 1, {INS_ld1r, INS_ld1r, INS_ld1r, INS_ld1r, INS_ld1r, INS_ld1r, INS_invalid, INS_invalid, INS_ld1r, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, LoadAndReplicateToVector128, 16, 1, {INS_ld1r, INS_ld1r, INS_ld1r, INS_ld1r, INS_ld1r, INS_ld1r, INS_invalid, INS_invalid, INS_ld1r, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, LoadVector64, 8, 1, {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, {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, Max, -1, 2, {INS_smax, INS_umax, INS_smax, INS_umax, INS_smax, INS_umax, INS_invalid, INS_invalid, INS_fmax, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, MaxNumber, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnm, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, MaxNumberScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnm, INS_fmaxnm}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, MaxPairwise, 8, 2, {INS_smaxp, INS_umaxp, INS_smaxp, INS_umaxp, INS_smaxp, INS_umaxp, INS_invalid, INS_invalid, INS_fmaxp, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, Min, -1, 2, {INS_smin, INS_umin, INS_smin, INS_umin, INS_smin, INS_umin, INS_invalid, INS_invalid, INS_fmin, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, MinNumber, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnm, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, MinNumberScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnm, INS_fminnm}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, MinPairwise, 8, 2, {INS_sminp, INS_uminp, INS_sminp, INS_uminp, INS_sminp, INS_uminp, INS_invalid, INS_invalid, INS_fminp, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, Multiply, -1, 2, {INS_mul, INS_mul, INS_mul, INS_mul, INS_mul, INS_mul, INS_invalid, INS_invalid, INS_fmul, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, MultiplyAdd, -1, 3, {INS_mla, INS_mla, INS_mla, INS_mla, INS_mla, INS_mla, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyAddByScalar, -1, 3, {INS_invalid, INS_invalid, INS_mla, INS_mla, INS_mla, INS_mla, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyAddBySelectedScalar, -1, 4, {INS_invalid, INS_invalid, INS_mla, INS_mla, INS_mla, INS_mla, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyByScalar, -1, 2, {INS_invalid, INS_invalid, INS_mul, INS_mul, INS_mul, INS_mul, INS_invalid, INS_invalid, INS_fmul, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, MultiplyBySelectedScalar, -1, 3, {INS_invalid, INS_invalid, INS_mul, INS_mul, INS_mul, INS_mul, INS_invalid, INS_invalid, INS_fmul, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, MultiplyBySelectedScalarWideningLower, 8, 3, {INS_invalid, INS_invalid, INS_smull, INS_umull, INS_smull, INS_umull, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, MultiplyBySelectedScalarWideningLowerAndAdd, 8, 4, {INS_invalid, INS_invalid, INS_smlal, INS_umlal, INS_smlal, INS_umlal, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyBySelectedScalarWideningLowerAndSubtract, 8, 4, {INS_invalid, INS_invalid, INS_smlsl, INS_umlsl, INS_smlsl, INS_umlsl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyBySelectedScalarWideningUpper, 16, 3, {INS_invalid, INS_invalid, INS_smull2, INS_umull2, INS_smull2, INS_umull2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, MultiplyBySelectedScalarWideningUpperAndAdd, 16, 4, {INS_invalid, INS_invalid, INS_smlal2, INS_umlal2, INS_smlal2, INS_umlal2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyBySelectedScalarWideningUpperAndSubtract, 16, 4, {INS_invalid, INS_invalid, INS_smlsl2, INS_umlsl2, INS_smlsl2, INS_umlsl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingByScalarSaturateHigh, -1, 2, {INS_invalid, INS_invalid, INS_sqdmulh, INS_invalid, INS_sqdmulh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingBySelectedScalarSaturateHigh, -1, 3, {INS_invalid, INS_invalid, INS_sqdmulh, INS_invalid, INS_sqdmulh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingSaturateHigh, -1, 2, {INS_invalid, INS_invalid, INS_sqdmulh, INS_invalid, INS_sqdmulh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningLowerAndAddSaturate, 8, 3, {INS_invalid, INS_invalid, INS_sqdmlal, INS_invalid, INS_sqdmlal, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningLowerAndSubtractSaturate, 8, 3, {INS_invalid, INS_invalid, INS_sqdmlsl, INS_invalid, INS_sqdmlsl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningLowerByScalarAndAddSaturate, 8, 3, {INS_invalid, INS_invalid, INS_sqdmlal, INS_invalid, INS_sqdmlal, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningLowerByScalarAndSubtractSaturate, 8, 3, {INS_invalid, INS_invalid, INS_sqdmlsl, INS_invalid, INS_sqdmlsl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningLowerBySelectedScalarAndAddSaturate, 8, 4, {INS_invalid, INS_invalid, INS_sqdmlal, INS_invalid, INS_sqdmlal, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningLowerBySelectedScalarAndSubtractSaturate, 8, 4, {INS_invalid, INS_invalid, INS_sqdmlsl, INS_invalid, INS_sqdmlsl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningSaturateLower, 8, 2, {INS_invalid, INS_invalid, INS_sqdmull, INS_invalid, INS_sqdmull, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningSaturateLowerByScalar, 8, 2, {INS_invalid, INS_invalid, INS_sqdmull, INS_invalid, INS_sqdmull, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningSaturateLowerBySelectedScalar, 8, 3, {INS_invalid, INS_invalid, INS_sqdmull, INS_invalid, INS_sqdmull, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningSaturateUpper, 16, 2, {INS_invalid, INS_invalid, INS_sqdmull2, INS_invalid, INS_sqdmull2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningSaturateUpperByScalar, 16, 2, {INS_invalid, INS_invalid, INS_sqdmull2, INS_invalid, INS_sqdmull2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningSaturateUpperBySelectedScalar, 16, 3, {INS_invalid, INS_invalid, INS_sqdmull2, INS_invalid, INS_sqdmull2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningUpperAndAddSaturate, 16, 3, {INS_invalid, INS_invalid, INS_sqdmlal2, INS_invalid, INS_sqdmlal2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningUpperAndSubtractSaturate, 16, 3, {INS_invalid, INS_invalid, INS_sqdmlsl2, INS_invalid, INS_sqdmlsl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningUpperByScalarAndAddSaturate, 16, 3, {INS_invalid, INS_invalid, INS_sqdmlal2, INS_invalid, INS_sqdmlal2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningUpperByScalarAndSubtractSaturate, 16, 3, {INS_invalid, INS_invalid, INS_sqdmlsl2, INS_invalid, INS_sqdmlsl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningUpperBySelectedScalarAndAddSaturate, 16, 4, {INS_invalid, INS_invalid, INS_sqdmlal2, INS_invalid, INS_sqdmlal2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningUpperBySelectedScalarAndSubtractSaturate, 16, 4, {INS_invalid, INS_invalid, INS_sqdmlsl2, INS_invalid, INS_sqdmlsl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyRoundedDoublingByScalarSaturateHigh, -1, 2, {INS_invalid, INS_invalid, INS_sqrdmulh, INS_invalid, INS_sqrdmulh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, MultiplyRoundedDoublingBySelectedScalarSaturateHigh, -1, 3, {INS_invalid, INS_invalid, INS_sqrdmulh, INS_invalid, INS_sqrdmulh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, MultiplyRoundedDoublingSaturateHigh, -1, 2, {INS_invalid, INS_invalid, INS_sqrdmulh, INS_invalid, INS_sqrdmulh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, MultiplyScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmul, INS_fmul}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, MultiplyScalarBySelectedScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmul, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, MultiplySubtract, -1, 3, {INS_mls, INS_mls, INS_mls, INS_mls, INS_mls, INS_mls, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplySubtractByScalar, -1, 3, {INS_invalid, INS_invalid, INS_mls, INS_mls, INS_mls, INS_mls, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplySubtractBySelectedScalar, -1, 4, {INS_invalid, INS_invalid, INS_mls, INS_mls, INS_mls, INS_mls, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningLower, 8, 2, {INS_smull, INS_umull, INS_smull, INS_umull, INS_smull, INS_umull, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningLowerAndAdd, 8, 3, {INS_smlal, INS_umlal, INS_smlal, INS_umlal, INS_smlal, INS_umlal, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningLowerAndSubtract, 8, 3, {INS_smlsl, INS_umlsl, INS_smlsl, INS_umlsl, INS_smlsl, INS_umlsl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningUpper, 16, 2, {INS_smull2, INS_umull2, INS_smull2, INS_umull2, INS_smull2, INS_umull2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningUpperAndAdd, 16, 3, {INS_smlal2, INS_umlal2, INS_smlal2, INS_umlal2, INS_smlal2, INS_umlal2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningUpperAndSubtract, 16, 3, {INS_smlsl2, INS_umlsl2, INS_smlsl2, INS_umlsl2, INS_smlsl2, INS_umlsl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, Negate, -1, 1, {INS_neg, INS_invalid, INS_neg, INS_invalid, INS_neg, INS_invalid, INS_invalid, INS_invalid, INS_fneg, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, NegateSaturate, -1, 1, {INS_sqneg, INS_invalid, INS_sqneg, INS_invalid, INS_sqneg, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, NegateScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fneg, INS_fneg}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, Not, -1, 1, {INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, Or, -1, 2, {INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, OrNot, -1, 2, {INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, PolynomialMultiply, -1, 2, {INS_pmul, INS_pmul, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, PolynomialMultiplyWideningLower, 8, 2, {INS_pmull, INS_pmull, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, PolynomialMultiplyWideningUpper, 16, 2, {INS_pmull2, INS_pmull2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, PopCount, -1, 1, {INS_cnt, INS_cnt, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, ReciprocalEstimate, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_urecpe, INS_invalid, INS_invalid, INS_frecpe, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, ReciprocalSquareRootEstimate, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ursqrte, INS_invalid, INS_invalid, INS_frsqrte, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, ReciprocalSquareRootStep, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frsqrts, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, ReciprocalStep, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecps, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, ReverseElement16, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_rev32, INS_rev32, INS_rev64, INS_rev64, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, ReverseElement32, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_rev64, INS_rev64, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, ReverseElement8, -1, 1, {INS_invalid, INS_invalid, INS_rev16, INS_rev16, INS_rev32, INS_rev32, INS_rev64, INS_rev64, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, RoundAwayFromZero, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frinta, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, RoundAwayFromZeroScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frinta, INS_frinta}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, RoundToNearest, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintn, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, RoundToNearestScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintn, INS_frintn}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, RoundToNegativeInfinity, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintm, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, RoundToNegativeInfinityScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintm, INS_frintm}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, RoundToPositiveInfinity, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, RoundToPositiveInfinityScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_frintp}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, RoundToZero, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintz, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, RoundToZeroScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintz, INS_frintz}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftArithmetic, -1, 2, {INS_sshl, INS_invalid, INS_sshl, INS_invalid, INS_sshl, INS_invalid, INS_sshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticRounded, -1, 2, {INS_srshl, INS_invalid, INS_srshl, INS_invalid, INS_srshl, INS_invalid, INS_srshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticRoundedSaturate, -1, 2, {INS_sqrshl, INS_invalid, INS_sqrshl, INS_invalid, INS_sqrshl, INS_invalid, INS_sqrshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticRoundedSaturateScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqrshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticRoundedScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_srshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticSaturate, -1, 2, {INS_sqshl, INS_invalid, INS_sqshl, INS_invalid, INS_sqshl, INS_invalid, INS_sqshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticSaturateScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftLeftAndInsert, -1, 3, {INS_sli, INS_sli, INS_sli, INS_sli, INS_sli, INS_sli, INS_sli, INS_sli, INS_sli, INS_sli}, HW_Category_ShiftLeftByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, ShiftLeftAndInsertScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sli, INS_sli, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogical, -1, 2, {INS_shl, INS_shl, INS_shl, INS_shl, INS_shl, INS_shl, INS_shl, INS_shl, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalSaturate, -1, 2, {INS_sqshl, INS_uqshl, INS_sqshl, INS_uqshl, INS_sqshl, INS_uqshl, INS_sqshl, INS_uqshl, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalSaturateScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqshl, INS_uqshl, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalSaturateUnsigned, -1, 2, {INS_sqshlu, INS_invalid, INS_sqshlu, INS_invalid, INS_sqshlu, INS_invalid, INS_sqshlu, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalSaturateUnsignedScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqshlu, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_shl, INS_shl, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalWideningLower, 8, 2, {INS_sshll, INS_ushll, INS_sshll, INS_ushll, INS_sshll, INS_ushll, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalWideningUpper, 16, 2, {INS_sshll2, INS_ushll2, INS_sshll2, INS_ushll2, INS_sshll2, INS_ushll2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, ShiftLogical, -1, 2, {INS_ushl, INS_ushl, INS_ushl, INS_ushl, INS_ushl, INS_ushl, INS_ushl, INS_ushl, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalRounded, -1, 2, {INS_urshl, INS_urshl, INS_urshl, INS_urshl, INS_urshl, INS_urshl, INS_urshl, INS_urshl, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalRoundedSaturate, -1, 2, {INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalRoundedSaturateScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_uqrshl, INS_uqrshl, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalRoundedScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_urshl, INS_urshl, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalSaturate, -1, 2, {INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalSaturateScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_uqshl, INS_uqshl, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ushl, INS_ushl, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightAndInsert, -1, 3, {INS_sri, INS_sri, INS_sri, INS_sri, INS_sri, INS_sri, INS_sri, INS_sri, INS_sri, INS_sri}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightAndInsertScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sri, INS_sri, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmetic, -1, 2, {INS_sshr, INS_invalid, INS_sshr, INS_invalid, INS_sshr, INS_invalid, INS_sshr, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticAdd, -1, 3, {INS_ssra, INS_invalid, INS_ssra, INS_invalid, INS_ssra, INS_invalid, INS_ssra, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticAddScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ssra, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticNarrowingSaturateLower, 8, 2, {INS_sqshrn, INS_invalid, INS_sqshrn, INS_invalid, INS_sqshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticNarrowingSaturateUnsignedLower, 8, 2, {INS_invalid, INS_sqshrun, INS_invalid, INS_sqshrun, INS_invalid, INS_sqshrun, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticNarrowingSaturateUnsignedUpper, 16, 3, {INS_invalid, INS_sqshrun2, INS_invalid, INS_sqshrun2, INS_invalid, INS_sqshrun2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticNarrowingSaturateUpper, 16, 3, {INS_sqshrn2, INS_invalid, INS_sqshrn2, INS_invalid, INS_sqshrn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRounded, -1, 2, {INS_srshr, INS_invalid, INS_srshr, INS_invalid, INS_srshr, INS_invalid, INS_srshr, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedAdd, -1, 3, {INS_srsra, INS_invalid, INS_srsra, INS_invalid, INS_srsra, INS_invalid, INS_srsra, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedAddScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_srsra, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedNarrowingSaturateLower, 8, 2, {INS_sqrshrn, INS_invalid, INS_sqrshrn, INS_invalid, INS_sqrshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower, 8, 2, {INS_invalid, INS_sqrshrun, INS_invalid, INS_sqrshrun, INS_invalid, INS_sqrshrun, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper, 16, 3, {INS_invalid, INS_sqrshrun2, INS_invalid, INS_sqrshrun2, INS_invalid, INS_sqrshrun2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedNarrowingSaturateUpper, 16, 3, {INS_sqrshrn2, INS_invalid, INS_sqrshrn2, INS_invalid, INS_sqrshrn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_srshr, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sshr, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogical, -1, 2, {INS_ushr, INS_ushr, INS_ushr, INS_ushr, INS_ushr, INS_ushr, INS_ushr, INS_ushr, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalAdd, -1, 3, {INS_usra, INS_usra, INS_usra, INS_usra, INS_usra, INS_usra, INS_usra, INS_usra, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalAddScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_usra, INS_usra, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalNarrowingLower, 8, 2, {INS_shrn, INS_shrn, INS_shrn, INS_shrn, INS_shrn, INS_shrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalNarrowingSaturateLower, 8, 2, {INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalNarrowingSaturateUpper, 16, 3, {INS_uqshrn2, INS_uqshrn2, INS_uqshrn2, INS_uqshrn2, INS_uqshrn2, INS_uqshrn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalNarrowingUpper, 16, 3, {INS_shrn2, INS_shrn2, INS_shrn2, INS_shrn2, INS_shrn2, INS_shrn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRounded, -1, 2, {INS_urshr, INS_urshr, INS_urshr, INS_urshr, INS_urshr, INS_urshr, INS_urshr, INS_urshr, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedAdd, -1, 3, {INS_ursra, INS_ursra, INS_ursra, INS_ursra, INS_ursra, INS_ursra, INS_ursra, INS_ursra, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedAddScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ursra, INS_ursra, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedNarrowingLower, 8, 2, {INS_rshrn, INS_rshrn, INS_rshrn, INS_rshrn, INS_rshrn, INS_rshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedNarrowingSaturateLower, 8, 2, {INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedNarrowingSaturateUpper, 16, 3, {INS_uqrshrn2, INS_uqrshrn2, INS_uqrshrn2, INS_uqrshrn2, INS_uqrshrn2, INS_uqrshrn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedNarrowingUpper, 16, 3, {INS_rshrn2, INS_rshrn2, INS_rshrn2, INS_rshrn2, INS_rshrn2, INS_rshrn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_urshr, INS_urshr, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ushr, INS_ushr, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, SignExtendWideningLower, 8, 1, {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, {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, {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, {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, StoreSelectedScalar, -1, 3, {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_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, Subtract, -1, 2, {INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_fsub, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, SubtractHighNarrowingLower, 8, 2, {INS_subhn, INS_subhn, INS_subhn, INS_subhn, INS_subhn, INS_subhn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, SubtractHighNarrowingUpper, 16, 3, {INS_subhn2, INS_subhn2, INS_subhn2, INS_subhn2, INS_subhn2, INS_subhn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, SubtractRoundedHighNarrowingLower, 8, 2, {INS_rsubhn, INS_rsubhn, INS_rsubhn, INS_rsubhn, INS_rsubhn, INS_rsubhn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, SubtractRoundedHighNarrowingUpper, 16, 3, {INS_rsubhn2, INS_rsubhn2, INS_rsubhn2, INS_rsubhn2, INS_rsubhn2, INS_rsubhn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd, SubtractSaturate, -1, 2, {INS_sqsub, INS_uqsub, INS_sqsub, INS_uqsub, INS_sqsub, INS_uqsub, INS_sqsub, INS_uqsub, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd, SubtractSaturateScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqsub, INS_uqsub, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, SubtractScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sub, INS_sub, INS_fsub, INS_fsub}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd, SubtractWideningLower, 8, 2, {INS_ssubl, INS_usubl, INS_ssubl, INS_usubl, INS_ssubl, INS_usubl, INS_ssubw, INS_usubw, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, SubtractWideningUpper, 16, 2, {INS_ssubl2, INS_usubl2, INS_ssubl2, INS_usubl2, INS_ssubl2, INS_usubl2, INS_ssubw2, INS_usubw2, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd, VectorTableLookup, 8, 2, {INS_tbl, INS_tbl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_NeedsConsecutiveRegisters) -HARDWARE_INTRINSIC(AdvSimd, VectorTableLookupExtension, 8, 3, {INS_tbx, INS_tbx, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics|HW_Flag_NeedsConsecutiveRegisters) -HARDWARE_INTRINSIC(AdvSimd, Xor, -1, 2, {INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd, ZeroExtendWideningLower, 8, 1, {INS_uxtl, INS_uxtl, INS_uxtl, INS_uxtl, INS_uxtl, INS_uxtl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd, ZeroExtendWideningUpper, 16, 1, {INS_uxtl2, INS_uxtl2, INS_uxtl2, INS_uxtl2, INS_uxtl2, INS_uxtl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, Abs, -1, 1, true, {INS_abs, INS_invalid, INS_abs, INS_invalid, INS_abs, INS_invalid, INS_invalid, INS_invalid, INS_fabs, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, AbsSaturate, -1, 1, true, {INS_sqabs, INS_invalid, INS_sqabs, INS_invalid, INS_sqabs, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, AbsScalar, 8, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fabs, INS_fabs}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, AbsoluteCompareGreaterThan, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, AbsoluteCompareGreaterThanOrEqual, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, AbsoluteCompareLessThan, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, AbsoluteCompareLessThanOrEqual, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifference, -1, 2, true, {INS_sabd, INS_uabd, INS_sabd, INS_uabd, INS_sabd, INS_uabd, INS_invalid, INS_invalid, INS_fabd, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifferenceAdd, -1, 3, true, {INS_saba, INS_uaba, INS_saba, INS_uaba, INS_saba, INS_uaba, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifferenceWideningLower, 8, 2, true, {INS_sabdl, INS_uabdl, INS_sabdl, INS_uabdl, INS_sabdl, INS_uabdl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifferenceWideningLowerAndAdd, 8, 3, true, {INS_sabal, INS_uabal, INS_sabal, INS_uabal, INS_sabal, INS_uabal, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifferenceWideningUpper, 16, 2, true, {INS_sabdl2, INS_uabdl2, INS_sabdl2, INS_uabdl2, INS_sabdl2, INS_uabdl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, AbsoluteDifferenceWideningUpperAndAdd, 16, 3, true, {INS_sabal2, INS_uabal2, INS_sabal2, INS_uabal2, INS_sabal2, INS_uabal2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, Add, -1, 2, true, {INS_add, INS_add, INS_add, INS_add, INS_add, INS_add, INS_add, INS_add, INS_fadd, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, AddHighNarrowingLower, 8, 2, true, {INS_addhn, INS_addhn, INS_addhn, INS_addhn, INS_addhn, INS_addhn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, AddHighNarrowingUpper, 16, 3, true, {INS_addhn2, INS_addhn2, INS_addhn2, INS_addhn2, INS_addhn2, INS_addhn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, AddPairwise, 8, 2, true, {INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_invalid, INS_invalid, INS_faddp, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, AddPairwiseWidening, -1, 1, true, {INS_saddlp, INS_uaddlp, INS_saddlp, INS_uaddlp, INS_saddlp, INS_uaddlp, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, AddPairwiseWideningAndAdd, -1, 2, true, {INS_sadalp, INS_uadalp, INS_sadalp, INS_uadalp, INS_sadalp, INS_uadalp, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, AddPairwiseWideningAndAddScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sadalp, INS_uadalp, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, AddPairwiseWideningScalar, 8, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_saddlp, INS_uaddlp, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, AddRoundedHighNarrowingLower, 8, 2, true, {INS_raddhn, INS_raddhn, INS_raddhn, INS_raddhn, INS_raddhn, INS_raddhn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, AddRoundedHighNarrowingUpper, 16, 3, true, {INS_raddhn2, INS_raddhn2, INS_raddhn2, INS_raddhn2, INS_raddhn2, INS_raddhn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, AddSaturate, -1, 2, true, {INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, AddSaturateScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqadd, INS_uqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, AddScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_add, INS_add, INS_fadd, INS_fadd}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, AddWideningLower, 8, 2, true, {INS_saddl, INS_uaddl, INS_saddl, INS_uaddl, INS_saddl, INS_uaddl, INS_saddw, INS_uaddw, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, AddWideningUpper, 16, 2, true, {INS_saddl2, INS_uaddl2, INS_saddl2, INS_uaddl2, INS_saddl2, INS_uaddl2, INS_saddw2, INS_uaddw2, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, And, -1, 2, true, {INS_and, INS_and, INS_and, INS_and, INS_and, INS_and, INS_and, INS_and, INS_and, INS_and}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, BitwiseClear, -1, 2, true, {INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic, INS_bic}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, BitwiseSelect, -1, 3, true, {INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl, INS_bsl}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, Ceiling, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, CeilingScalar, 8, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_frintp}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, CompareEqual, -1, 2, true, {INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_cmeq, INS_invalid, INS_invalid, INS_fcmeq, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThan, -1, 2, true, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd, CompareGreaterThanOrEqual, -1, 2, true, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SIMD, HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd, CompareLessThan, -1, 2, true, {INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_cmgt, INS_cmhi, INS_invalid, INS_invalid, INS_fcmgt, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, CompareLessThanOrEqual, -1, 2, true, {INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_cmge, INS_cmhs, INS_invalid, INS_invalid, INS_fcmge, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, CompareTest, -1, 2, true, {INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_cmtst, INS_invalid, INS_invalid, INS_cmtst, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, ConvertToInt32RoundAwayFromZero, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtas, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, ConvertToInt32RoundAwayFromZeroScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtas, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ConvertToInt32RoundToEven, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtns, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, ConvertToInt32RoundToEvenScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtns, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ConvertToInt32RoundToNegativeInfinity, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtms, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, ConvertToInt32RoundToNegativeInfinityScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtms, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ConvertToInt32RoundToPositiveInfinity, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtps, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, ConvertToInt32RoundToPositiveInfinityScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtps, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ConvertToInt32RoundToZero, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtzs, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, ConvertToInt32RoundToZeroScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtzs, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ConvertToSingle, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_scvtf, INS_ucvtf, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, ConvertToSingleScalar, 8, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_scvtf, INS_ucvtf, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ConvertToUInt32RoundAwayFromZero, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtau, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, ConvertToUInt32RoundAwayFromZeroScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtau, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ConvertToUInt32RoundToEven, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtnu, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, ConvertToUInt32RoundToEvenScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtnu, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ConvertToUInt32RoundToNegativeInfinity, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtmu, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, ConvertToUInt32RoundToNegativeInfinityScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtmu, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ConvertToUInt32RoundToPositiveInfinity, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtpu, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, ConvertToUInt32RoundToPositiveInfinityScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtpu, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ConvertToUInt32RoundToZero, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtzu, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, ConvertToUInt32RoundToZeroScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtzu, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, DivideScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fdiv, INS_fdiv}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, DuplicateSelectedScalarToVector64, -1, 2, true, {INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_invalid, INS_invalid, INS_dup, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, DuplicateSelectedScalarToVector128, -1, 2, true, {INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_invalid, INS_invalid, INS_dup, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, DuplicateToVector64, 8, 1, true, {INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_invalid, INS_invalid, INS_dup, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd, DuplicateToVector128, 16, 1, true, {INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_dup, INS_invalid, INS_invalid, INS_dup, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd, Extract, -1, 2, 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_HasImmediateOperand|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ExtractNarrowingLower, 8, 1, true, {INS_xtn, INS_xtn, INS_xtn, INS_xtn, INS_xtn, INS_xtn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ExtractNarrowingSaturateLower, 8, 1, true, {INS_sqxtn, INS_uqxtn, INS_sqxtn, INS_uqxtn, INS_sqxtn, INS_uqxtn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ExtractNarrowingSaturateUnsignedLower, 8, 1, true, {INS_invalid, INS_sqxtun, INS_invalid, INS_sqxtun, INS_invalid, INS_sqxtun, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ExtractNarrowingSaturateUnsignedUpper, 16, 2, true, {INS_invalid, INS_sqxtun2, INS_invalid, INS_sqxtun2, INS_invalid, INS_sqxtun2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ExtractNarrowingSaturateUpper, 16, 2, true, {INS_sqxtn2, INS_uqxtn2, INS_sqxtn2, INS_uqxtn2, INS_sqxtn2, INS_uqxtn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ExtractNarrowingUpper, 16, 2, true, {INS_xtn2, INS_xtn2, INS_xtn2, INS_xtn2, INS_xtn2, INS_xtn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ExtractVector64, 8, 3, true, {INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_ext, INS_invalid, INS_invalid, INS_ext, INS_invalid}, HW_Category_SIMD, HW_Flag_HasImmediateOperand|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ExtractVector128, 16, 3, 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_HasImmediateOperand|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, Floor, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintm, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, FloorScalar, 8, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintm, INS_frintm}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, FusedAddHalving, -1, 2, true, {INS_shadd, INS_uhadd, INS_shadd, INS_uhadd, INS_shadd, INS_uhadd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, FusedAddRoundedHalving, -1, 2, true, {INS_srhadd, INS_urhadd, INS_srhadd, INS_urhadd, INS_srhadd, INS_urhadd, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, FusedMultiplyAdd, -1, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmla, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, FusedMultiplyAddScalar, 8, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmadd, INS_fmadd}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, FusedMultiplyAddNegatedScalar, 8, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fnmadd, INS_fnmadd}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, FusedMultiplySubtract, -1, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmls, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, FusedMultiplySubtractScalar, 8, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmsub, INS_fmsub}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, FusedMultiplySubtractNegatedScalar, 8, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fnmsub, INS_fnmsub}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, FusedSubtractHalving, -1, 2, true, {INS_shsub, INS_uhsub, INS_shsub, INS_uhsub, INS_shsub, INS_uhsub, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, Insert, -1, 3, true, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins}, HW_Category_SIMD, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd, InsertScalar, 16, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ins, INS_ins, INS_invalid, INS_ins}, HW_Category_SIMD, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, LeadingSignCount, -1, 1, true, {INS_cls, INS_invalid, INS_cls, INS_invalid, INS_cls, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, LeadingZeroCount, -1, 1, true, {INS_clz, INS_clz, INS_clz, INS_clz, INS_clz, INS_clz, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, LoadAndInsertScalar, -1, 3, true, {INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1, INS_ld1}, HW_Category_MemoryLoad, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, LoadAndReplicateToVector64, 8, 1, true, {INS_ld1r, INS_ld1r, INS_ld1r, INS_ld1r, INS_ld1r, INS_ld1r, INS_invalid, INS_invalid, INS_ld1r, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, LoadAndReplicateToVector128, 16, 1, true, {INS_ld1r, INS_ld1r, INS_ld1r, INS_ld1r, INS_ld1r, INS_ld1r, INS_invalid, INS_invalid, INS_ld1r, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoFlag) +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, Max, -1, 2, true, {INS_smax, INS_umax, INS_smax, INS_umax, INS_smax, INS_umax, INS_invalid, INS_invalid, INS_fmax, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, MaxNumber, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnm, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, MaxNumberScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnm, INS_fmaxnm}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, MaxPairwise, 8, 2, true, {INS_smaxp, INS_umaxp, INS_smaxp, INS_umaxp, INS_smaxp, INS_umaxp, INS_invalid, INS_invalid, INS_fmaxp, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, Min, -1, 2, true, {INS_smin, INS_umin, INS_smin, INS_umin, INS_smin, INS_umin, INS_invalid, INS_invalid, INS_fmin, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, MinNumber, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnm, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, MinNumberScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnm, INS_fminnm}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, MinPairwise, 8, 2, true, {INS_sminp, INS_uminp, INS_sminp, INS_uminp, INS_sminp, INS_uminp, INS_invalid, INS_invalid, INS_fminp, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, Multiply, -1, 2, true, {INS_mul, INS_mul, INS_mul, INS_mul, INS_mul, INS_mul, INS_invalid, INS_invalid, INS_fmul, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, MultiplyAdd, -1, 3, true, {INS_mla, INS_mla, INS_mla, INS_mla, INS_mla, INS_mla, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyAddByScalar, -1, 3, true, {INS_invalid, INS_invalid, INS_mla, INS_mla, INS_mla, INS_mla, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyAddBySelectedScalar, -1, 4, true, {INS_invalid, INS_invalid, INS_mla, INS_mla, INS_mla, INS_mla, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyByScalar, -1, 2, true, {INS_invalid, INS_invalid, INS_mul, INS_mul, INS_mul, INS_mul, INS_invalid, INS_invalid, INS_fmul, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, MultiplyBySelectedScalar, -1, 3, true, {INS_invalid, INS_invalid, INS_mul, INS_mul, INS_mul, INS_mul, INS_invalid, INS_invalid, INS_fmul, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, MultiplyBySelectedScalarWideningLower, 8, 3, true, {INS_invalid, INS_invalid, INS_smull, INS_umull, INS_smull, INS_umull, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, MultiplyBySelectedScalarWideningLowerAndAdd, 8, 4, true, {INS_invalid, INS_invalid, INS_smlal, INS_umlal, INS_smlal, INS_umlal, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyBySelectedScalarWideningLowerAndSubtract, 8, 4, true, {INS_invalid, INS_invalid, INS_smlsl, INS_umlsl, INS_smlsl, INS_umlsl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyBySelectedScalarWideningUpper, 16, 3, true, {INS_invalid, INS_invalid, INS_smull2, INS_umull2, INS_smull2, INS_umull2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, MultiplyBySelectedScalarWideningUpperAndAdd, 16, 4, true, {INS_invalid, INS_invalid, INS_smlal2, INS_umlal2, INS_smlal2, INS_umlal2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyBySelectedScalarWideningUpperAndSubtract, 16, 4, true, {INS_invalid, INS_invalid, INS_smlsl2, INS_umlsl2, INS_smlsl2, INS_umlsl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingByScalarSaturateHigh, -1, 2, true, {INS_invalid, INS_invalid, INS_sqdmulh, INS_invalid, INS_sqdmulh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingBySelectedScalarSaturateHigh, -1, 3, true, {INS_invalid, INS_invalid, INS_sqdmulh, INS_invalid, INS_sqdmulh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingSaturateHigh, -1, 2, true, {INS_invalid, INS_invalid, INS_sqdmulh, INS_invalid, INS_sqdmulh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningLowerAndAddSaturate, 8, 3, true, {INS_invalid, INS_invalid, INS_sqdmlal, INS_invalid, INS_sqdmlal, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningLowerAndSubtractSaturate, 8, 3, true, {INS_invalid, INS_invalid, INS_sqdmlsl, INS_invalid, INS_sqdmlsl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningLowerByScalarAndAddSaturate, 8, 3, true, {INS_invalid, INS_invalid, INS_sqdmlal, INS_invalid, INS_sqdmlal, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningLowerByScalarAndSubtractSaturate, 8, 3, true, {INS_invalid, INS_invalid, INS_sqdmlsl, INS_invalid, INS_sqdmlsl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningLowerBySelectedScalarAndAddSaturate, 8, 4, true, {INS_invalid, INS_invalid, INS_sqdmlal, INS_invalid, INS_sqdmlal, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningLowerBySelectedScalarAndSubtractSaturate, 8, 4, true, {INS_invalid, INS_invalid, INS_sqdmlsl, INS_invalid, INS_sqdmlsl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningSaturateLower, 8, 2, true, {INS_invalid, INS_invalid, INS_sqdmull, INS_invalid, INS_sqdmull, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningSaturateLowerByScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_sqdmull, INS_invalid, INS_sqdmull, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningSaturateLowerBySelectedScalar, 8, 3, true, {INS_invalid, INS_invalid, INS_sqdmull, INS_invalid, INS_sqdmull, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningSaturateUpper, 16, 2, true, {INS_invalid, INS_invalid, INS_sqdmull2, INS_invalid, INS_sqdmull2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningSaturateUpperByScalar, 16, 2, true, {INS_invalid, INS_invalid, INS_sqdmull2, INS_invalid, INS_sqdmull2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningSaturateUpperBySelectedScalar, 16, 3, true, {INS_invalid, INS_invalid, INS_sqdmull2, INS_invalid, INS_sqdmull2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningUpperAndAddSaturate, 16, 3, true, {INS_invalid, INS_invalid, INS_sqdmlal2, INS_invalid, INS_sqdmlal2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningUpperAndSubtractSaturate, 16, 3, true, {INS_invalid, INS_invalid, INS_sqdmlsl2, INS_invalid, INS_sqdmlsl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningUpperByScalarAndAddSaturate, 16, 3, true, {INS_invalid, INS_invalid, INS_sqdmlal2, INS_invalid, INS_sqdmlal2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningUpperByScalarAndSubtractSaturate, 16, 3, true, {INS_invalid, INS_invalid, INS_sqdmlsl2, INS_invalid, INS_sqdmlsl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningUpperBySelectedScalarAndAddSaturate, 16, 4, true, {INS_invalid, INS_invalid, INS_sqdmlal2, INS_invalid, INS_sqdmlal2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyDoublingWideningUpperBySelectedScalarAndSubtractSaturate, 16, 4, true, {INS_invalid, INS_invalid, INS_sqdmlsl2, INS_invalid, INS_sqdmlsl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyRoundedDoublingByScalarSaturateHigh, -1, 2, true, {INS_invalid, INS_invalid, INS_sqrdmulh, INS_invalid, INS_sqrdmulh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, MultiplyRoundedDoublingBySelectedScalarSaturateHigh, -1, 3, true, {INS_invalid, INS_invalid, INS_sqrdmulh, INS_invalid, INS_sqrdmulh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, MultiplyRoundedDoublingSaturateHigh, -1, 2, true, {INS_invalid, INS_invalid, INS_sqrdmulh, INS_invalid, INS_sqrdmulh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, MultiplyScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmul, INS_fmul}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, MultiplyScalarBySelectedScalar, 8, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmul, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, MultiplySubtract, -1, 3, true, {INS_mls, INS_mls, INS_mls, INS_mls, INS_mls, INS_mls, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplySubtractByScalar, -1, 3, true, {INS_invalid, INS_invalid, INS_mls, INS_mls, INS_mls, INS_mls, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplySubtractBySelectedScalar, -1, 4, true, {INS_invalid, INS_invalid, INS_mls, INS_mls, INS_mls, INS_mls, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningLower, 8, 2, true, {INS_smull, INS_umull, INS_smull, INS_umull, INS_smull, INS_umull, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningLowerAndAdd, 8, 3, true, {INS_smlal, INS_umlal, INS_smlal, INS_umlal, INS_smlal, INS_umlal, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningLowerAndSubtract, 8, 3, true, {INS_smlsl, INS_umlsl, INS_smlsl, INS_umlsl, INS_smlsl, INS_umlsl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningUpper, 16, 2, true, {INS_smull2, INS_umull2, INS_smull2, INS_umull2, INS_smull2, INS_umull2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningUpperAndAdd, 16, 3, true, {INS_smlal2, INS_umlal2, INS_smlal2, INS_umlal2, INS_smlal2, INS_umlal2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, MultiplyWideningUpperAndSubtract, 16, 3, true, {INS_smlsl2, INS_umlsl2, INS_smlsl2, INS_umlsl2, INS_smlsl2, INS_umlsl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, Negate, -1, 1, true, {INS_neg, INS_invalid, INS_neg, INS_invalid, INS_neg, INS_invalid, INS_invalid, INS_invalid, INS_fneg, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, NegateSaturate, -1, 1, true, {INS_sqneg, INS_invalid, INS_sqneg, INS_invalid, INS_sqneg, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, NegateScalar, 8, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fneg, INS_fneg}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, Not, -1, 1, true, {INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn, INS_mvn}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, Or, -1, 2, true, {INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr, INS_orr}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, OrNot, -1, 2, true, {INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn, INS_orn}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, PolynomialMultiply, -1, 2, true, {INS_pmul, INS_pmul, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, PolynomialMultiplyWideningLower, 8, 2, true, {INS_pmull, INS_pmull, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, PolynomialMultiplyWideningUpper, 16, 2, true, {INS_pmull2, INS_pmull2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, PopCount, -1, 1, true, {INS_cnt, INS_cnt, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ReciprocalEstimate, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_urecpe, INS_invalid, INS_invalid, INS_frecpe, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ReciprocalSquareRootEstimate, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ursqrte, INS_invalid, INS_invalid, INS_frsqrte, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ReciprocalSquareRootStep, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frsqrts, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, ReciprocalStep, -1, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecps, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, ReverseElement16, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_rev32, INS_rev32, INS_rev64, INS_rev64, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ReverseElement32, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_rev64, INS_rev64, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, ReverseElement8, -1, 1, true, {INS_invalid, INS_invalid, INS_rev16, INS_rev16, INS_rev32, INS_rev32, INS_rev64, INS_rev64, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, RoundAwayFromZero, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frinta, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, RoundAwayFromZeroScalar, 8, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frinta, INS_frinta}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, RoundToNearest, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintn, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, RoundToNearestScalar, 8, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintn, INS_frintn}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, RoundToNegativeInfinity, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintm, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, RoundToNegativeInfinityScalar, 8, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintm, INS_frintm}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, RoundToPositiveInfinity, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, RoundToPositiveInfinityScalar, 8, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp, INS_frintp}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, RoundToZero, -1, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintz, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, RoundToZeroScalar, 8, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintz, INS_frintz}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftArithmetic, -1, 2, true, {INS_sshl, INS_invalid, INS_sshl, INS_invalid, INS_sshl, INS_invalid, INS_sshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticRounded, -1, 2, true, {INS_srshl, INS_invalid, INS_srshl, INS_invalid, INS_srshl, INS_invalid, INS_srshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticRoundedSaturate, -1, 2, true, {INS_sqrshl, INS_invalid, INS_sqrshl, INS_invalid, INS_sqrshl, INS_invalid, INS_sqrshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticRoundedSaturateScalar, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqrshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticRoundedScalar, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_srshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticSaturate, -1, 2, true, {INS_sqshl, INS_invalid, INS_sqshl, INS_invalid, INS_sqshl, INS_invalid, INS_sqshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticSaturateScalar, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftArithmeticScalar, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sshl, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftLeftAndInsert, -1, 3, true, {INS_sli, INS_sli, INS_sli, INS_sli, INS_sli, INS_sli, INS_sli, INS_sli, INS_sli, INS_sli}, HW_Category_ShiftLeftByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftLeftAndInsertScalar, 8, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sli, INS_sli, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogical, -1, 2, true, {INS_shl, INS_shl, INS_shl, INS_shl, INS_shl, INS_shl, INS_shl, INS_shl, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalSaturate, -1, 2, true, {INS_sqshl, INS_uqshl, INS_sqshl, INS_uqshl, INS_sqshl, INS_uqshl, INS_sqshl, INS_uqshl, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalSaturateScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqshl, INS_uqshl, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalSaturateUnsigned, -1, 2, true, {INS_sqshlu, INS_invalid, INS_sqshlu, INS_invalid, INS_sqshlu, INS_invalid, INS_sqshlu, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalSaturateUnsignedScalar, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqshlu, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_shl, INS_shl, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalWideningLower, 8, 2, true, {INS_sshll, INS_ushll, INS_sshll, INS_ushll, INS_sshll, INS_ushll, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, ShiftLeftLogicalWideningUpper, 16, 2, true, {INS_sshll2, INS_ushll2, INS_sshll2, INS_ushll2, INS_sshll2, INS_ushll2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, ShiftLogical, -1, 2, true, {INS_ushl, INS_ushl, INS_ushl, INS_ushl, INS_ushl, INS_ushl, INS_ushl, INS_ushl, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalRounded, -1, 2, true, {INS_urshl, INS_urshl, INS_urshl, INS_urshl, INS_urshl, INS_urshl, INS_urshl, INS_urshl, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalRoundedSaturate, -1, 2, true, {INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalRoundedSaturateScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_uqrshl, INS_uqrshl, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalRoundedScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_urshl, INS_urshl, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalSaturate, -1, 2, true, {INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalSaturateScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_uqshl, INS_uqshl, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftLogicalScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ushl, INS_ushl, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightAndInsert, -1, 3, true, {INS_sri, INS_sri, INS_sri, INS_sri, INS_sri, INS_sri, INS_sri, INS_sri, INS_sri, INS_sri}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightAndInsertScalar, 8, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sri, INS_sri, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmetic, -1, 2, true, {INS_sshr, INS_invalid, INS_sshr, INS_invalid, INS_sshr, INS_invalid, INS_sshr, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticAdd, -1, 3, true, {INS_ssra, INS_invalid, INS_ssra, INS_invalid, INS_ssra, INS_invalid, INS_ssra, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticAddScalar, 8, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ssra, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticNarrowingSaturateLower, 8, 2, true, {INS_sqshrn, INS_invalid, INS_sqshrn, INS_invalid, INS_sqshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticNarrowingSaturateUnsignedLower, 8, 2, true, {INS_invalid, INS_sqshrun, INS_invalid, INS_sqshrun, INS_invalid, INS_sqshrun, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticNarrowingSaturateUnsignedUpper, 16, 3, true, {INS_invalid, INS_sqshrun2, INS_invalid, INS_sqshrun2, INS_invalid, INS_sqshrun2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticNarrowingSaturateUpper, 16, 3, true, {INS_sqshrn2, INS_invalid, INS_sqshrn2, INS_invalid, INS_sqshrn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRounded, -1, 2, true, {INS_srshr, INS_invalid, INS_srshr, INS_invalid, INS_srshr, INS_invalid, INS_srshr, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedAdd, -1, 3, true, {INS_srsra, INS_invalid, INS_srsra, INS_invalid, INS_srsra, INS_invalid, INS_srsra, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedAddScalar, 8, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_srsra, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedNarrowingSaturateLower, 8, 2, true, {INS_sqrshrn, INS_invalid, INS_sqrshrn, INS_invalid, INS_sqrshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedNarrowingSaturateUnsignedLower, 8, 2, true, {INS_invalid, INS_sqrshrun, INS_invalid, INS_sqrshrun, INS_invalid, INS_sqrshrun, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedNarrowingSaturateUnsignedUpper, 16, 3, true, {INS_invalid, INS_sqrshrun2, INS_invalid, INS_sqrshrun2, INS_invalid, INS_sqrshrun2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedNarrowingSaturateUpper, 16, 3, true, {INS_sqrshrn2, INS_invalid, INS_sqrshrn2, INS_invalid, INS_sqrshrn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticRoundedScalar, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_srshr, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightArithmeticScalar, 8, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sshr, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogical, -1, 2, true, {INS_ushr, INS_ushr, INS_ushr, INS_ushr, INS_ushr, INS_ushr, INS_ushr, INS_ushr, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalAdd, -1, 3, true, {INS_usra, INS_usra, INS_usra, INS_usra, INS_usra, INS_usra, INS_usra, INS_usra, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalAddScalar, 8, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_usra, INS_usra, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalNarrowingLower, 8, 2, true, {INS_shrn, INS_shrn, INS_shrn, INS_shrn, INS_shrn, INS_shrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalNarrowingSaturateLower, 8, 2, true, {INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalNarrowingSaturateUpper, 16, 3, true, {INS_uqshrn2, INS_uqshrn2, INS_uqshrn2, INS_uqshrn2, INS_uqshrn2, INS_uqshrn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalNarrowingUpper, 16, 3, true, {INS_shrn2, INS_shrn2, INS_shrn2, INS_shrn2, INS_shrn2, INS_shrn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRounded, -1, 2, true, {INS_urshr, INS_urshr, INS_urshr, INS_urshr, INS_urshr, INS_urshr, INS_urshr, INS_urshr, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedAdd, -1, 3, true, {INS_ursra, INS_ursra, INS_ursra, INS_ursra, INS_ursra, INS_ursra, INS_ursra, INS_ursra, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedAddScalar, 8, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ursra, INS_ursra, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedNarrowingLower, 8, 2, true, {INS_rshrn, INS_rshrn, INS_rshrn, INS_rshrn, INS_rshrn, INS_rshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedNarrowingSaturateLower, 8, 2, true, {INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedNarrowingSaturateUpper, 16, 3, true, {INS_uqrshrn2, INS_uqrshrn2, INS_uqrshrn2, INS_uqrshrn2, INS_uqrshrn2, INS_uqrshrn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedNarrowingUpper, 16, 3, true, {INS_rshrn2, INS_rshrn2, INS_rshrn2, INS_rshrn2, INS_rshrn2, INS_rshrn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalRoundedScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_urshr, INS_urshr, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, ShiftRightLogicalScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ushr, INS_ushr, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +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, StoreSelectedScalar, -1, 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_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, Subtract, -1, 2, true, {INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_sub, INS_fsub, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, SubtractHighNarrowingLower, 8, 2, true, {INS_subhn, INS_subhn, INS_subhn, INS_subhn, INS_subhn, INS_subhn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, SubtractHighNarrowingUpper, 16, 3, true, {INS_subhn2, INS_subhn2, INS_subhn2, INS_subhn2, INS_subhn2, INS_subhn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, SubtractRoundedHighNarrowingLower, 8, 2, true, {INS_rsubhn, INS_rsubhn, INS_rsubhn, INS_rsubhn, INS_rsubhn, INS_rsubhn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, SubtractRoundedHighNarrowingUpper, 16, 3, true, {INS_rsubhn2, INS_rsubhn2, INS_rsubhn2, INS_rsubhn2, INS_rsubhn2, INS_rsubhn2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd, SubtractSaturate, -1, 2, true, {INS_sqsub, INS_uqsub, INS_sqsub, INS_uqsub, INS_sqsub, INS_uqsub, INS_sqsub, INS_uqsub, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd, SubtractSaturateScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqsub, INS_uqsub, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, SubtractScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sub, INS_sub, INS_fsub, INS_fsub}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd, SubtractWideningLower, 8, 2, true, {INS_ssubl, INS_usubl, INS_ssubl, INS_usubl, INS_ssubl, INS_usubl, INS_ssubw, INS_usubw, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, SubtractWideningUpper, 16, 2, true, {INS_ssubl2, INS_usubl2, INS_ssubl2, INS_usubl2, INS_ssubl2, INS_usubl2, INS_ssubw2, INS_usubw2, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd, VectorTableLookup, 8, 2, true, {INS_tbl, INS_tbl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_NeedsConsecutiveRegisters) +HARDWARE_INTRINSIC(AdvSimd, VectorTableLookupExtension, 8, 3, true, {INS_tbx, INS_tbx, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics|HW_Flag_NeedsConsecutiveRegisters) +HARDWARE_INTRINSIC(AdvSimd, Xor, -1, 2, true, {INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor, INS_eor}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd, ZeroExtendWideningLower, 8, 1, true, {INS_uxtl, INS_uxtl, INS_uxtl, INS_uxtl, INS_uxtl, INS_uxtl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd, ZeroExtendWideningUpper, 16, 1, true, {INS_uxtl2, INS_uxtl2, INS_uxtl2, INS_uxtl2, INS_uxtl2, INS_uxtl2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size Number of arguments Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // AdvSimd 64-bit only Intrinsics -HARDWARE_INTRINSIC(AdvSimd_Arm64, Abs, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_abs, INS_invalid, INS_invalid, INS_fabs}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsSaturate, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqabs, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsSaturateScalar, 8, 1, {INS_sqabs, INS_invalid, INS_sqabs, INS_invalid, INS_sqabs, INS_invalid, INS_sqabs, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_abs, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareGreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareGreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareGreaterThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge, INS_facge}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareGreaterThanScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt, INS_facgt}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareLessThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareLessThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareLessThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge, INS_facge}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareLessThanScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt, INS_facgt}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteDifference, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fabd}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteDifferenceScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fabd, INS_fabd}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, Add, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fadd}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AddAcross, -1, 1, {INS_addv, INS_addv, INS_addv, INS_addv, INS_addv, INS_addv, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AddAcrossWidening, -1, 1, {INS_saddlv, INS_uaddlv, INS_saddlv, INS_uaddlv, INS_saddlv, INS_uaddlv, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AddPairwise, 16, 2, {INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_faddp, INS_faddp}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AddPairwiseScalar, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_addp, INS_addp, INS_faddp, INS_faddp}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AddSaturate, -1, 2, {INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd_Arm64, AddSaturateScalar, 8, 2, {INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_suqadd, INS_usqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, Ceiling, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_invalid, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_fcmeq, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar|HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SIMD, HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_fcmgt, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThan, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThanOrEqual, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThanOrEqualScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThanScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_fcmgt, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareTest, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmtst, INS_cmtst, INS_invalid, INS_cmtst}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareTestScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmtst, INS_cmtst, INS_invalid, INS_cmtst}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToDouble, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_scvtf, INS_ucvtf, INS_fcvtl, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToDoubleScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_scvtf, INS_ucvtf, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToDoubleUpper, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtl2, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToInt64RoundAwayFromZero, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtas}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToInt64RoundAwayFromZeroScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtas}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToInt64RoundToEven, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtns}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToInt64RoundToEvenScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtns}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToInt64RoundToNegativeInfinity, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtms}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToInt64RoundToNegativeInfinityScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtms}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToInt64RoundToPositiveInfinity, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtps}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToInt64RoundToPositiveInfinityScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtps}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToInt64RoundToZero, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtzs}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToInt64RoundToZeroScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtzs}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToSingleLower, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtn, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToSingleRoundToOddLower, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtxn, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToSingleRoundToOddUpper, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtxn2, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToSingleUpper, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtn2, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToUInt64RoundAwayFromZero, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtau}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToUInt64RoundAwayFromZeroScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtau}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToUInt64RoundToEven, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtnu}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToUInt64RoundToEvenScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtnu}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToUInt64RoundToNegativeInfinity, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtmu}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToUInt64RoundToNegativeInfinityScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtmu}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToUInt64RoundToPositiveInfinity, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtpu}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToUInt64RoundToPositiveInfinityScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtpu}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToUInt64RoundToZero, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtzu}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToUInt64RoundToZeroScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtzu}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, Divide, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fdiv, INS_fdiv}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, DuplicateSelectedScalarToVector128, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_dup, INS_dup, INS_invalid, INS_dup}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, DuplicateToVector64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov, INS_mov, INS_invalid, INS_fmov}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd_Arm64, DuplicateToVector128, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_dup, INS_dup, INS_invalid, INS_dup}, HW_Category_SIMD, HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ExtractNarrowingSaturateScalar, 8, 1, {INS_sqxtn, INS_uqxtn, INS_sqxtn, INS_uqxtn, INS_sqxtn, INS_uqxtn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ExtractNarrowingSaturateUnsignedScalar, 8, 1, {INS_invalid, INS_sqxtun, INS_invalid, INS_sqxtun, INS_invalid, INS_sqxtun, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, Floor, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintm}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplyAdd, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmla}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplyAddByScalar, -1, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmla, INS_fmla}, HW_Category_SIMDByIndexedElement, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplyAddBySelectedScalar, -1, 4, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmla, INS_fmla}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplyAddScalarBySelectedScalar, 8, 4, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmla, INS_fmla}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplySubtract, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmls}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplySubtractByScalar, -1, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmls, INS_fmls}, HW_Category_SIMDByIndexedElement, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplySubtractBySelectedScalar, -1, 4, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmls, INS_fmls}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplySubtractScalarBySelectedScalar, 8, 4, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmls, INS_fmls}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, InsertSelectedScalar, -1, 4, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins}, HW_Category_SIMD, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_NoJmpTableIMM|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadAndReplicateToVector128, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ld1r, INS_ld1r, INS_invalid, INS_ld1r}, HW_Category_MemoryLoad, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadPairScalarVector64, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ldp, INS_ldp, INS_invalid, INS_invalid, INS_ldp, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_MultiReg|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadPairScalarVector64NonTemporal, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ldnp, INS_ldnp, INS_invalid, INS_invalid, INS_ldnp, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_MultiReg|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadPairVector64, 8, 1, {INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_MultiReg|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadPairVector64NonTemporal, 8, 1, {INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_MultiReg|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadPairVector128, 16, 1, {INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_MultiReg|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadPairVector128NonTemporal, 16, 1, {INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_MultiReg|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) -HARDWARE_INTRINSIC(AdvSimd_Arm64, Max, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmax}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxAcross, -1, 1, {INS_smaxv, INS_umaxv, INS_smaxv, INS_umaxv, INS_smaxv, INS_umaxv, INS_invalid, INS_invalid, INS_fmaxv, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxNumber, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnm}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxNumberAcross, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnmv, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxNumberPairwise, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnmp, INS_fmaxnmp}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxNumberPairwiseScalar, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnmp, INS_fmaxnmp}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxPairwise, 16, 2, {INS_smaxp, INS_umaxp, INS_smaxp, INS_umaxp, INS_smaxp, INS_umaxp, INS_invalid, INS_invalid, INS_fmaxp, INS_fmaxp}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxPairwiseScalar, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxp, INS_fmaxp}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmax, INS_fmax}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, Min, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmin}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MinAcross, -1, 1, {INS_sminv, INS_uminv, INS_sminv, INS_uminv, INS_sminv, INS_uminv, INS_invalid, INS_invalid, INS_fminv, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MinNumber, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnm}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MinNumberAcross, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnmv, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MinNumberPairwise, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnmp, INS_fminnmp}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MinNumberPairwiseScalar, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnmp, INS_fminnmp}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MinPairwise, 16, 2, {INS_sminp, INS_uminp, INS_sminp, INS_uminp, INS_sminp, INS_uminp, INS_invalid, INS_invalid, INS_fminp, INS_fminp}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MinPairwiseScalar, -1, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminp, INS_fminp}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MinScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmin, INS_fmin}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, Multiply, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmul}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyByScalar, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmul}, HW_Category_SIMDByIndexedElement, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyBySelectedScalar, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmul}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyDoublingSaturateHighScalar, 8, 2, {INS_invalid, INS_invalid, INS_sqdmulh, INS_invalid, INS_sqdmulh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyDoublingScalarBySelectedScalarSaturateHigh, 8, 3, {INS_invalid, INS_invalid, INS_sqdmulh, INS_invalid, INS_sqdmulh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyDoublingWideningAndAddSaturateScalar, 8, 3, {INS_invalid, INS_invalid, INS_sqdmlal, INS_invalid, INS_sqdmlal, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyDoublingWideningAndSubtractSaturateScalar, 8, 3, {INS_invalid, INS_invalid, INS_sqdmlsl, INS_invalid, INS_sqdmlsl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyDoublingWideningSaturateScalar, 8, 2, {INS_invalid, INS_invalid, INS_sqdmull, INS_invalid, INS_sqdmull, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyDoublingWideningSaturateScalarBySelectedScalar, 8, 3, {INS_invalid, INS_invalid, INS_sqdmull, INS_invalid, INS_sqdmull, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyDoublingWideningScalarBySelectedScalarAndAddSaturate, 8, 4, {INS_invalid, INS_invalid, INS_sqdmlal, INS_invalid, INS_sqdmlal, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyDoublingWideningScalarBySelectedScalarAndSubtractSaturate, 8, 4, {INS_invalid, INS_invalid, INS_sqdmlsl, INS_invalid, INS_sqdmlsl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyExtended, -1, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmulx, INS_fmulx}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyExtendedByScalar, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmulx}, HW_Category_SIMDByIndexedElement, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyExtendedBySelectedScalar, -1, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmulx, INS_fmulx}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyExtendedScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmulx, INS_fmulx}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyExtendedScalarBySelectedScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmulx, INS_fmulx}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyRoundedDoublingSaturateHighScalar, 8, 2, {INS_invalid, INS_invalid, INS_sqrdmulh, INS_invalid, INS_sqrdmulh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyRoundedDoublingScalarBySelectedScalarSaturateHigh, 8, 3, {INS_invalid, INS_invalid, INS_sqrdmulh, INS_invalid, INS_sqrdmulh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyScalarBySelectedScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmul}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, Negate, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_neg, INS_invalid, INS_invalid, INS_fneg}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, NegateSaturate, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqneg, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, NegateSaturateScalar, 8, 1, {INS_sqneg, INS_invalid, INS_sqneg, INS_invalid, INS_sqneg, INS_invalid, INS_sqneg, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, NegateScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_neg, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalEstimate, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecpe}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalEstimateScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecpe, INS_frecpe}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalExponentScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecpx, INS_frecpx}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalSquareRootEstimate, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frsqrte}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalSquareRootEstimateScalar, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frsqrte, INS_frsqrte}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalSquareRootStep, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frsqrts}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalSquareRootStepScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frsqrts, INS_frsqrts}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalStep, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecps}, HW_Category_SIMD, HW_Flag_Commutative) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalStepScalar, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecps, INS_frecps}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ReverseElementBits, -1, 1, {INS_rbit, INS_rbit, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, RoundAwayFromZero, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frinta}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, RoundToNearest, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintn}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, RoundToNegativeInfinity, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintm}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, RoundToPositiveInfinity, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, RoundToZero, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintz}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftArithmeticRoundedSaturateScalar, 8, 2, {INS_sqrshl, INS_invalid, INS_sqrshl, INS_invalid, INS_sqrshl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftArithmeticSaturateScalar, 8, 2, {INS_sqshl, INS_invalid, INS_sqshl, INS_invalid, INS_sqshl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftLeftLogicalSaturateScalar, 8, 2, {INS_sqshl, INS_uqshl, INS_sqshl, INS_uqshl, INS_sqshl, INS_uqshl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftLeftLogicalSaturateUnsignedScalar, 8, 2, {INS_sqshlu, INS_invalid, INS_sqshlu, INS_invalid, INS_sqshlu, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftLogicalRoundedSaturateScalar, 8, 2, {INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftLogicalSaturateScalar, 8, 2, {INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftRightArithmeticNarrowingSaturateScalar, 8, 2, {INS_sqshrn, INS_invalid, INS_sqshrn, INS_invalid, INS_sqshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftRightArithmeticNarrowingSaturateUnsignedScalar, 8, 2, {INS_invalid, INS_sqshrun, INS_invalid, INS_sqshrun, INS_invalid, INS_sqshrun, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftRightArithmeticRoundedNarrowingSaturateScalar, 8, 2, {INS_sqrshrn, INS_invalid, INS_sqrshrn, INS_invalid, INS_sqrshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar, 8, 2, {INS_invalid, INS_sqrshrun, INS_invalid, INS_sqrshrun, INS_invalid, INS_sqrshrun, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftRightLogicalNarrowingSaturateScalar, 8, 2, {INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftRightLogicalRoundedNarrowingSaturateScalar, 8, 2, {INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, Sqrt, -1, 1, {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_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, StorePair, -1, 3, {INS_stp, INS_stp, INS_stp, INS_stp, INS_stp, INS_stp, INS_stp, INS_stp, INS_stp, INS_stp}, HW_Category_MemoryStore, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, StorePairScalar, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_stp, INS_stp, INS_invalid, INS_invalid, INS_stp, INS_invalid}, HW_Category_MemoryStore, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, StorePairScalarNonTemporal, 8, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_stnp, INS_stnp, INS_invalid, INS_invalid, INS_stnp, INS_invalid}, HW_Category_MemoryStore, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, StorePairNonTemporal, -1, 3, {INS_stnp, INS_stnp, INS_stnp, INS_stnp, INS_stnp, INS_stnp, INS_stnp, INS_stnp, INS_stnp, INS_stp}, HW_Category_MemoryStore, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AdvSimd_Arm64, Subtract, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fsub}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, SubtractSaturateScalar, 8, 2, {INS_sqsub, INS_uqsub, INS_sqsub, INS_uqsub, INS_sqsub, INS_uqsub, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(AdvSimd_Arm64, TransposeEven, -1, 2, {INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, TransposeOdd, -1, 2, {INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, UnzipEven, -1, 2, {INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, UnzipOdd, -1, 2, {INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, VectorTableLookup, 16, 2, {INS_tbl, INS_tbl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_NeedsConsecutiveRegisters) -HARDWARE_INTRINSIC(AdvSimd_Arm64, VectorTableLookupExtension, 16, 3, {INS_tbx, INS_tbx, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics|HW_Flag_NeedsConsecutiveRegisters) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ZipHigh, -1, 2, {INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AdvSimd_Arm64, ZipLow, -1, 2, {INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, Abs, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_abs, INS_invalid, INS_invalid, INS_fabs}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsSaturate, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqabs, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsSaturateScalar, 8, 1, true, {INS_sqabs, INS_invalid, INS_sqabs, INS_invalid, INS_sqabs, INS_invalid, INS_sqabs, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_abs, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareGreaterThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareGreaterThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareGreaterThanOrEqualScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge, INS_facge}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareGreaterThanScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt, INS_facgt}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareLessThan, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareLessThanOrEqual, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareLessThanOrEqualScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facge, INS_facge}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteCompareLessThanScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_facgt, INS_facgt}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteDifference, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fabd}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AbsoluteDifferenceScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fabd, INS_fabd}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, Add, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fadd}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AddAcross, -1, 1, true, {INS_addv, INS_addv, INS_addv, INS_addv, INS_addv, INS_addv, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AddAcrossWidening, -1, 1, true, {INS_saddlv, INS_uaddlv, INS_saddlv, INS_uaddlv, INS_saddlv, INS_uaddlv, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AddPairwise, 16, 2, true, {INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_addp, INS_faddp, INS_faddp}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AddPairwiseScalar, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_addp, INS_addp, INS_faddp, INS_faddp}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AddSaturate, -1, 2, true, {INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_suqadd, INS_usqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd_Arm64, AddSaturateScalar, 8, 2, true, {INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_sqadd, INS_uqadd, INS_suqadd, INS_usqadd, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, Ceiling, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqual, 16, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_invalid, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareEqualScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmeq, INS_cmeq, INS_fcmeq, INS_fcmeq}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThan, 16, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqual, 16, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SIMD, HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanOrEqualScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareGreaterThanScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_fcmgt, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThan, 16, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_invalid, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThanOrEqual, 16, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_invalid, INS_fcmge}, HW_Category_SIMD, HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThanOrEqualScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmge, INS_cmhs, INS_fcmge, INS_fcmge}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareLessThanScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmgt, INS_cmhi, INS_fcmgt, INS_fcmgt}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareTest, 16, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmtst, INS_cmtst, INS_invalid, INS_cmtst}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, CompareTestScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmtst, INS_cmtst, INS_invalid, INS_cmtst}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToDouble, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_scvtf, INS_ucvtf, INS_fcvtl, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToDoubleScalar, 8, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_scvtf, INS_ucvtf, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToDoubleUpper, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtl2, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToInt64RoundAwayFromZero, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtas}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToInt64RoundAwayFromZeroScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtas}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToInt64RoundToEven, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtns}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToInt64RoundToEvenScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtns}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToInt64RoundToNegativeInfinity, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtms}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToInt64RoundToNegativeInfinityScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtms}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToInt64RoundToPositiveInfinity, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtps}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToInt64RoundToPositiveInfinityScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtps}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToInt64RoundToZero, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtzs}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToInt64RoundToZeroScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtzs}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToSingleLower, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtn, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToSingleRoundToOddLower, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtxn, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToSingleRoundToOddUpper, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtxn2, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToSingleUpper, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtn2, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToUInt64RoundAwayFromZero, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtau}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToUInt64RoundAwayFromZeroScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtau}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToUInt64RoundToEven, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtnu}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToUInt64RoundToEvenScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtnu}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToUInt64RoundToNegativeInfinity, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtmu}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToUInt64RoundToNegativeInfinityScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtmu}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToUInt64RoundToPositiveInfinity, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtpu}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToUInt64RoundToPositiveInfinityScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtpu}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToUInt64RoundToZero, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtzu}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ConvertToUInt64RoundToZeroScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fcvtzu}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, Divide, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fdiv, INS_fdiv}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, DuplicateSelectedScalarToVector128, 16, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_dup, INS_dup, INS_invalid, INS_dup}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, DuplicateToVector64, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_mov, INS_mov, INS_invalid, INS_fmov}, HW_Category_SIMD, HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, DuplicateToVector128, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_dup, INS_dup, INS_invalid, INS_dup}, HW_Category_SIMD, HW_Flag_SpecialCodeGen|HW_Flag_SupportsContainment) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ExtractNarrowingSaturateScalar, 8, 1, true, {INS_sqxtn, INS_uqxtn, INS_sqxtn, INS_uqxtn, INS_sqxtn, INS_uqxtn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ExtractNarrowingSaturateUnsignedScalar, 8, 1, true, {INS_invalid, INS_sqxtun, INS_invalid, INS_sqxtun, INS_invalid, INS_sqxtun, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, Floor, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintm}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplyAdd, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmla}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplyAddByScalar, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmla, INS_fmla}, HW_Category_SIMDByIndexedElement, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplyAddBySelectedScalar, -1, 4, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmla, INS_fmla}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplyAddScalarBySelectedScalar, 8, 4, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmla, INS_fmla}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplySubtract, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmls}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplySubtractByScalar, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmls, INS_fmls}, HW_Category_SIMDByIndexedElement, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplySubtractBySelectedScalar, -1, 4, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmls, INS_fmls}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(AdvSimd_Arm64, FusedMultiplySubtractScalarBySelectedScalar, 8, 4, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmls, INS_fmls}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, InsertSelectedScalar, -1, 4, true, {INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins, INS_ins}, HW_Category_SIMD, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_NoJmpTableIMM|HW_Flag_SIMDScalar|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadAndReplicateToVector128, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ld1r, INS_ld1r, INS_invalid, INS_ld1r}, HW_Category_MemoryLoad, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadPairScalarVector64, 8, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ldp, INS_ldp, INS_invalid, INS_invalid, INS_ldp, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_MultiReg|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) +HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadPairScalarVector64NonTemporal, 8, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_ldnp, INS_ldnp, INS_invalid, INS_invalid, INS_ldnp, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_MultiReg|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) +HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadPairVector64, 8, 1, true, {INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_MultiReg|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) +HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadPairVector64NonTemporal, 8, 1, true, {INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_MultiReg|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) +HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadPairVector128, 16, 1, true, {INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp, INS_ldp}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_MultiReg|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) +HARDWARE_INTRINSIC(AdvSimd_Arm64, LoadPairVector128NonTemporal, 16, 1, true, {INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp, INS_ldnp}, HW_Category_MemoryLoad, HW_Flag_BaseTypeFromFirstArg|HW_Flag_MultiReg|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport) +HARDWARE_INTRINSIC(AdvSimd_Arm64, Max, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmax}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxAcross, -1, 1, true, {INS_smaxv, INS_umaxv, INS_smaxv, INS_umaxv, INS_smaxv, INS_umaxv, INS_invalid, INS_invalid, INS_fmaxv, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxNumber, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnm}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxNumberAcross, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnmv, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxNumberPairwise, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnmp, INS_fmaxnmp}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxNumberPairwiseScalar, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxnmp, INS_fmaxnmp}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxPairwise, 16, 2, true, {INS_smaxp, INS_umaxp, INS_smaxp, INS_umaxp, INS_smaxp, INS_umaxp, INS_invalid, INS_invalid, INS_fmaxp, INS_fmaxp}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxPairwiseScalar, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmaxp, INS_fmaxp}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MaxScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmax, INS_fmax}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, Min, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmin}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MinAcross, -1, 1, true, {INS_sminv, INS_uminv, INS_sminv, INS_uminv, INS_sminv, INS_uminv, INS_invalid, INS_invalid, INS_fminv, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MinNumber, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnm}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MinNumberAcross, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnmv, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MinNumberPairwise, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnmp, INS_fminnmp}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MinNumberPairwiseScalar, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminnmp, INS_fminnmp}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MinPairwise, 16, 2, true, {INS_sminp, INS_uminp, INS_sminp, INS_uminp, INS_sminp, INS_uminp, INS_invalid, INS_invalid, INS_fminp, INS_fminp}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MinPairwiseScalar, -1, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fminp, INS_fminp}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MinScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmin, INS_fmin}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, Multiply, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmul}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyByScalar, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmul}, HW_Category_SIMDByIndexedElement, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyBySelectedScalar, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmul}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyDoublingSaturateHighScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_sqdmulh, INS_invalid, INS_sqdmulh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyDoublingScalarBySelectedScalarSaturateHigh, 8, 3, true, {INS_invalid, INS_invalid, INS_sqdmulh, INS_invalid, INS_sqdmulh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyDoublingWideningAndAddSaturateScalar, 8, 3, true, {INS_invalid, INS_invalid, INS_sqdmlal, INS_invalid, INS_sqdmlal, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyDoublingWideningAndSubtractSaturateScalar, 8, 3, true, {INS_invalid, INS_invalid, INS_sqdmlsl, INS_invalid, INS_sqdmlsl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyDoublingWideningSaturateScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_sqdmull, INS_invalid, INS_sqdmull, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyDoublingWideningSaturateScalarBySelectedScalar, 8, 3, true, {INS_invalid, INS_invalid, INS_sqdmull, INS_invalid, INS_sqdmull, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyDoublingWideningScalarBySelectedScalarAndAddSaturate, 8, 4, true, {INS_invalid, INS_invalid, INS_sqdmlal, INS_invalid, INS_sqdmlal, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyDoublingWideningScalarBySelectedScalarAndSubtractSaturate, 8, 4, true, {INS_invalid, INS_invalid, INS_sqdmlsl, INS_invalid, INS_sqdmlsl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_BaseTypeFromSecondArg|HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyExtended, -1, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmulx, INS_fmulx}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyExtendedByScalar, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmulx}, HW_Category_SIMDByIndexedElement, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyExtendedBySelectedScalar, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmulx, INS_fmulx}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyExtendedScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmulx, INS_fmulx}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyExtendedScalarBySelectedScalar, 8, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmulx, INS_fmulx}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyRoundedDoublingSaturateHighScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_sqrdmulh, INS_invalid, INS_sqrdmulh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyRoundedDoublingScalarBySelectedScalarSaturateHigh, 8, 3, true, {INS_invalid, INS_invalid, INS_sqrdmulh, INS_invalid, INS_sqrdmulh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, MultiplyScalarBySelectedScalar, 8, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fmul}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, Negate, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_neg, INS_invalid, INS_invalid, INS_fneg}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, NegateSaturate, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sqneg, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, NegateSaturateScalar, 8, 1, true, {INS_sqneg, INS_invalid, INS_sqneg, INS_invalid, INS_sqneg, INS_invalid, INS_sqneg, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, NegateScalar, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_neg, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalEstimate, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecpe}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalEstimateScalar, 8, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecpe, INS_frecpe}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalExponentScalar, 8, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecpx, INS_frecpx}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalSquareRootEstimate, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frsqrte}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalSquareRootEstimateScalar, 8, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frsqrte, INS_frsqrte}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalSquareRootStep, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frsqrts}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalSquareRootStepScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frsqrts, INS_frsqrts}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalStep, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecps}, HW_Category_SIMD, HW_Flag_Commutative) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ReciprocalStepScalar, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frecps, INS_frecps}, HW_Category_SIMD, HW_Flag_Commutative|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ReverseElementBits, -1, 1, true, {INS_rbit, INS_rbit, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, RoundAwayFromZero, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frinta}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, RoundToNearest, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintn}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, RoundToNegativeInfinity, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintm}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, RoundToPositiveInfinity, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintp}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, RoundToZero, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_frintz}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftArithmeticRoundedSaturateScalar, 8, 2, true, {INS_sqrshl, INS_invalid, INS_sqrshl, INS_invalid, INS_sqrshl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftArithmeticSaturateScalar, 8, 2, true, {INS_sqshl, INS_invalid, INS_sqshl, INS_invalid, INS_sqshl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftLeftLogicalSaturateScalar, 8, 2, true, {INS_sqshl, INS_uqshl, INS_sqshl, INS_uqshl, INS_sqshl, INS_uqshl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftLeftLogicalSaturateUnsignedScalar, 8, 2, true, {INS_sqshlu, INS_invalid, INS_sqshlu, INS_invalid, INS_sqshlu, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftLeftByImmediate, HW_Flag_BaseTypeFromFirstArg|HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftLogicalRoundedSaturateScalar, 8, 2, true, {INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_uqrshl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftLogicalSaturateScalar, 8, 2, true, {INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_uqshl, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftRightArithmeticNarrowingSaturateScalar, 8, 2, true, {INS_sqshrn, INS_invalid, INS_sqshrn, INS_invalid, INS_sqshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftRightArithmeticNarrowingSaturateUnsignedScalar, 8, 2, true, {INS_invalid, INS_sqshrun, INS_invalid, INS_sqshrun, INS_invalid, INS_sqshrun, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftRightArithmeticRoundedNarrowingSaturateScalar, 8, 2, true, {INS_sqrshrn, INS_invalid, INS_sqrshrn, INS_invalid, INS_sqrshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftRightArithmeticRoundedNarrowingSaturateUnsignedScalar, 8, 2, true, {INS_invalid, INS_sqrshrun, INS_invalid, INS_sqrshrun, INS_invalid, INS_sqrshrun, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftRightLogicalNarrowingSaturateScalar, 8, 2, true, {INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_uqshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ShiftRightLogicalRoundedNarrowingSaturateScalar, 8, 2, true, {INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_uqrshrn, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_ShiftRightByImmediate, HW_Flag_HasImmediateOperand|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, Sqrt, -1, 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_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, StorePair, -1, 3, true, {INS_stp, INS_stp, INS_stp, INS_stp, INS_stp, INS_stp, INS_stp, INS_stp, INS_stp, INS_stp}, HW_Category_MemoryStore, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, StorePairScalar, 8, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_stp, INS_stp, INS_invalid, INS_invalid, INS_stp, INS_invalid}, HW_Category_MemoryStore, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, StorePairScalarNonTemporal, 8, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_stnp, INS_stnp, INS_invalid, INS_invalid, INS_stnp, INS_invalid}, HW_Category_MemoryStore, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, StorePairNonTemporal, -1, 3, true, {INS_stnp, INS_stnp, INS_stnp, INS_stnp, INS_stnp, INS_stnp, INS_stnp, INS_stnp, INS_stnp, INS_stp}, HW_Category_MemoryStore, HW_Flag_BaseTypeFromSecondArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AdvSimd_Arm64, Subtract, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_fsub}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, SubtractSaturateScalar, 8, 2, true, {INS_sqsub, INS_uqsub, INS_sqsub, INS_uqsub, INS_sqsub, INS_uqsub, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(AdvSimd_Arm64, TransposeEven, -1, 2, true, {INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1, INS_trn1}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, TransposeOdd, -1, 2, true, {INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2, INS_trn2}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, UnzipEven, -1, 2, true, {INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1, INS_uzp1}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, UnzipOdd, -1, 2, true, {INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2, INS_uzp2}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, VectorTableLookup, 16, 2, true, {INS_tbl, INS_tbl, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_NeedsConsecutiveRegisters) +HARDWARE_INTRINSIC(AdvSimd_Arm64, VectorTableLookupExtension, 16, 3, true, {INS_tbx, INS_tbx, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_HasRMWSemantics|HW_Flag_NeedsConsecutiveRegisters) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ZipHigh, -1, 2, true, {INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2, INS_zip2}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(AdvSimd_Arm64, ZipLow, -1, 2, true, {INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1, INS_zip1}, HW_Category_SIMD, HW_Flag_NoFlag) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size Number of arguments Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // AES Intrinsics -HARDWARE_INTRINSIC(Aes, Decrypt, 16, 2, {INS_invalid, INS_aesd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Aes, Encrypt, 16, 2, {INS_invalid, INS_aese, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Aes, InverseMixColumns, 16, 1, {INS_invalid, INS_aesimc, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(Aes, MixColumns, 16, 1, {INS_invalid, INS_aesmc, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(Aes, PolynomialMultiplyWideningLower, 8, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmull, INS_pmull, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) -HARDWARE_INTRINSIC(Aes, PolynomialMultiplyWideningUpper, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmull2, INS_pmull2, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) +HARDWARE_INTRINSIC(Aes, Decrypt, 16, 2, false, {INS_invalid, INS_aesd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Aes, Encrypt, 16, 2, false, {INS_invalid, INS_aese, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Aes, InverseMixColumns, 16, 1, false, {INS_invalid, INS_aesimc, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(Aes, MixColumns, 16, 1, false, {INS_invalid, INS_aesmc, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_NoFlag) +HARDWARE_INTRINSIC(Aes, PolynomialMultiplyWideningLower, 8, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmull, INS_pmull, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) +HARDWARE_INTRINSIC(Aes, PolynomialMultiplyWideningUpper, 16, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pmull2, INS_pmull2, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_Commutative) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size Number of arguments Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Base Intrinsics -HARDWARE_INTRINSIC(ArmBase, LeadingZeroCount, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_clz, INS_clz, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoFloatingPointUsed) -HARDWARE_INTRINSIC(ArmBase, ReverseElementBits, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_rbit, INS_rbit, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed) -HARDWARE_INTRINSIC(ArmBase, Yield, 0, 0, {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_NoFloatingPointUsed|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport|HW_Flag_SpecialSideEffect_Other) +HARDWARE_INTRINSIC(ArmBase, LeadingZeroCount, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_clz, INS_clz, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoFloatingPointUsed) +HARDWARE_INTRINSIC(ArmBase, ReverseElementBits, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_rbit, INS_rbit, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed) +HARDWARE_INTRINSIC(ArmBase, Yield, 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_NoFloatingPointUsed|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport|HW_Flag_SpecialSideEffect_Other) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size Number of arguments Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Base 64-bit only Intrinsics -HARDWARE_INTRINSIC(ArmBase_Arm64, LeadingSignCount, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cls, INS_invalid, INS_cls, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoFloatingPointUsed) -HARDWARE_INTRINSIC(ArmBase_Arm64, LeadingZeroCount, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_clz, INS_clz, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoFloatingPointUsed) -HARDWARE_INTRINSIC(ArmBase_Arm64, MultiplyHigh, 0, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_smulh, INS_umulh, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed) -HARDWARE_INTRINSIC(ArmBase_Arm64, ReverseElementBits, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_rbit, INS_rbit, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed) +HARDWARE_INTRINSIC(ArmBase_Arm64, LeadingSignCount, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cls, INS_invalid, INS_cls, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoFloatingPointUsed) +HARDWARE_INTRINSIC(ArmBase_Arm64, LeadingZeroCount, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_clz, INS_clz, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoFloatingPointUsed) +HARDWARE_INTRINSIC(ArmBase_Arm64, MultiplyHigh, 0, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_smulh, INS_umulh, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed) +HARDWARE_INTRINSIC(ArmBase_Arm64, ReverseElementBits, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_rbit, INS_rbit, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size Number of arguments Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // CRC32 Intrinsics -HARDWARE_INTRINSIC(Crc32, ComputeCrc32, 0, 2, {INS_invalid, INS_crc32b, INS_invalid, INS_crc32h, INS_invalid, INS_crc32w, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_NoFloatingPointUsed|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(Crc32, ComputeCrc32C, 0, 2, {INS_invalid, INS_crc32cb, INS_invalid, INS_crc32ch, INS_invalid, INS_crc32cw, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_NoFloatingPointUsed|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Crc32, ComputeCrc32, 0, 2, false, {INS_invalid, INS_crc32b, INS_invalid, INS_crc32h, INS_invalid, INS_crc32w, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_NoFloatingPointUsed|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Crc32, ComputeCrc32C, 0, 2, false, {INS_invalid, INS_crc32cb, INS_invalid, INS_crc32ch, INS_invalid, INS_crc32cw, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_NoFloatingPointUsed|HW_Flag_SpecialCodeGen) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size Number of arguments Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // CRC32 64-bit only Intrinsics -HARDWARE_INTRINSIC(Crc32_Arm64, ComputeCrc32, 0, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_crc32x, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_NoFloatingPointUsed|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(Crc32_Arm64, ComputeCrc32C, 0, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_crc32cx, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_NoFloatingPointUsed|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Crc32_Arm64, ComputeCrc32, 0, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_crc32x, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_NoFloatingPointUsed|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(Crc32_Arm64, ComputeCrc32C, 0, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_crc32cx, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_NoFloatingPointUsed|HW_Flag_SpecialCodeGen) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size Number of arguments Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // DP Intrinsics -HARDWARE_INTRINSIC(Dp, DotProduct, -1, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sdot, INS_udot, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Dp, DotProductBySelectedQuadruplet, -1, 4, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sdot, INS_udot, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Dp, DotProduct, -1, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sdot, INS_udot, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Dp, DotProductBySelectedQuadruplet, -1, 4, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sdot, INS_udot, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size Number of arguments Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // RDM Intrinsics -HARDWARE_INTRINSIC(Rdm, MultiplyRoundedDoublingAndAddSaturateHigh, -1, 3, {INS_invalid, INS_invalid, INS_sqrdmlah, INS_invalid, INS_sqrdmlah, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Rdm, MultiplyRoundedDoublingAndSubtractSaturateHigh, -1, 3, {INS_invalid, INS_invalid, INS_sqrdmlsh, INS_invalid, INS_sqrdmlsh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Rdm, MultiplyRoundedDoublingBySelectedScalarAndAddSaturateHigh, -1, 4, {INS_invalid, INS_invalid, INS_sqrdmlah, INS_invalid, INS_sqrdmlah, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Rdm, MultiplyRoundedDoublingBySelectedScalarAndSubtractSaturateHigh, -1, 4, {INS_invalid, INS_invalid, INS_sqrdmlsh, INS_invalid, INS_sqrdmlsh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Rdm, MultiplyRoundedDoublingAndAddSaturateHigh, -1, 3, true, {INS_invalid, INS_invalid, INS_sqrdmlah, INS_invalid, INS_sqrdmlah, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Rdm, MultiplyRoundedDoublingAndSubtractSaturateHigh, -1, 3, true, {INS_invalid, INS_invalid, INS_sqrdmlsh, INS_invalid, INS_sqrdmlsh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Rdm, MultiplyRoundedDoublingBySelectedScalarAndAddSaturateHigh, -1, 4, true, {INS_invalid, INS_invalid, INS_sqrdmlah, INS_invalid, INS_sqrdmlah, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Rdm, MultiplyRoundedDoublingBySelectedScalarAndSubtractSaturateHigh, -1, 4, true, {INS_invalid, INS_invalid, INS_sqrdmlsh, INS_invalid, INS_sqrdmlsh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size Number of arguments Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // RDM 64-bit only Intrinsics -HARDWARE_INTRINSIC(Rdm_Arm64, MultiplyRoundedDoublingAndAddSaturateHighScalar, 8, 3, {INS_invalid, INS_invalid, INS_sqrdmlah, INS_invalid, INS_sqrdmlah, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(Rdm_Arm64, MultiplyRoundedDoublingAndSubtractSaturateHighScalar, 8, 3, {INS_invalid, INS_invalid, INS_sqrdmlsh, INS_invalid, INS_sqrdmlsh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(Rdm_Arm64, MultiplyRoundedDoublingScalarBySelectedScalarAndAddSaturateHigh, 8, 4, {INS_invalid, INS_invalid, INS_sqrdmlah, INS_invalid, INS_sqrdmlah, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(Rdm_Arm64, MultiplyRoundedDoublingScalarBySelectedScalarAndSubtractSaturateHigh, 8, 4, {INS_invalid, INS_invalid, INS_sqrdmlsh, INS_invalid, INS_sqrdmlsh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(Rdm_Arm64, MultiplyRoundedDoublingAndAddSaturateHighScalar, 8, 3, true, {INS_invalid, INS_invalid, INS_sqrdmlah, INS_invalid, INS_sqrdmlah, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(Rdm_Arm64, MultiplyRoundedDoublingAndSubtractSaturateHighScalar, 8, 3, true, {INS_invalid, INS_invalid, INS_sqrdmlsh, INS_invalid, INS_sqrdmlsh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(Rdm_Arm64, MultiplyRoundedDoublingScalarBySelectedScalarAndAddSaturateHigh, 8, 4, true, {INS_invalid, INS_invalid, INS_sqrdmlah, INS_invalid, INS_sqrdmlah, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(Rdm_Arm64, MultiplyRoundedDoublingScalarBySelectedScalarAndSubtractSaturateHigh, 8, 4, true, {INS_invalid, INS_invalid, INS_sqrdmlsh, INS_invalid, INS_sqrdmlsh, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDByIndexedElement, HW_Flag_HasImmediateOperand|HW_Flag_HasRMWSemantics|HW_Flag_SIMDScalar) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size Number of arguments Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // SHA1 Intrinsics -HARDWARE_INTRINSIC(Sha1, FixedRotate, 8, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1h, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) -HARDWARE_INTRINSIC(Sha1, HashUpdateChoose, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1c, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Sha1, HashUpdateMajority, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1m, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Sha1, HashUpdateParity, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1p, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Sha1, ScheduleUpdate0, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1su0, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Sha1, ScheduleUpdate1, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1su1, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sha1, FixedRotate, 8, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1h, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_SIMDScalar) +HARDWARE_INTRINSIC(Sha1, HashUpdateChoose, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1c, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sha1, HashUpdateMajority, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1m, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sha1, HashUpdateParity, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1p, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sha1, ScheduleUpdate0, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1su0, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sha1, ScheduleUpdate1, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha1su1, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size Number of arguments Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // SHA256 Intrinsics -HARDWARE_INTRINSIC(Sha256, HashUpdate1, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha256h, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Sha256, HashUpdate2, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha256h2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Sha256, ScheduleUpdate0, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha256su0, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) -HARDWARE_INTRINSIC(Sha256, ScheduleUpdate1, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha256su1, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sha256, HashUpdate1, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha256h, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sha256, HashUpdate2, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha256h2, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sha256, ScheduleUpdate0, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha256su0, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) +HARDWARE_INTRINSIC(Sha256, ScheduleUpdate1, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_sha256su1, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMD, HW_Flag_HasRMWSemantics) #endif // FEATURE_HW_INTRINSIC diff --git a/src/coreclr/jit/hwintrinsiclistxarch.h b/src/coreclr/jit/hwintrinsiclistxarch.h index b804d4a0edd5d3..e1649b2159c55f 100644 --- a/src/coreclr/jit/hwintrinsiclistxarch.h +++ b/src/coreclr/jit/hwintrinsiclistxarch.h @@ -17,1272 +17,1297 @@ 4) SIMD intrinsics have a non-zero `SIMD size` field based-on that operate over `Vector128`(16) or `Vector256`(32) 5) Scalar intrinsics that operate over general purpose registers (e.g., Sse41.Crc32) have `SIMD size` with 0 6) Each intrinsic has a `NumArg` for number of parameters, and some intrinsics that are overloaded on multiple parameter numbers have this field with -1 - 7) Each intrinsic has 10 `instructions` fields that list the instructions should be generated based-on the base type - 8) Each intrinsic has one category with type of `enum HWIntrinsicCategory`, please see the definition of HWIntrinsicCategory for details - 9) Each intrinsic has one or more flags with type of `enum HWIntrinsicFlag` + 7) Each intrinsic has a `EncodesExtraTypeArg` when a type argument is needed to distinguish between multiple intrinsics + (This matches the value of Compiler::vnEncodesResultTypeForHWIntrinsic.) + 8) Each intrinsic has 10 `instructions` fields that list the instructions should be generated based-on the base type + 9) Each intrinsic has one category with type of `enum HWIntrinsicCategory`, please see the definition of HWIntrinsicCategory for details + 10) Each intrinsic has one or more flags with type of `enum HWIntrinsicFlag` */ // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Vector128 Intrinsics -HARDWARE_INTRINSIC(Vector128, Abs, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Add, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AndNot, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, As, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsByte, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsDouble, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsInt16, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsInt32, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsNInt, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsNUInt, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsSByte, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsSingle, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsUInt16, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsUInt32, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsUInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsVector, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, AsVector2, 16, 1, {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, {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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, Create, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, CreateScalar, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, CreateScalarUnsafe, 16, 1, {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, Divide, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Dot, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Equals, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Vector128, EqualsAll, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, EqualsAny, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ExtractMostSignificantBits, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Floor, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, get_AllBitsSet, 16, 0, {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_One, 16, 0, {INS_invalid, INS_invalid, INS_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, {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, GetElement, 16, 2, {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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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_Equality, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(Vector128, op_ExclusiveOr, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_Inequality, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(Vector128, op_LeftShift, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_Multiply, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_OnesComplement, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_RightShift, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_Subtraction, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_UnaryNegation, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_UnaryPlus, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, op_UnsignedRightShift, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ShiftLeft, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ShiftRightArithmetic, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ShiftRightLogical, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Shuffle, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Sqrt, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Store, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, StoreAligned, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, StoreAlignedNonTemporal, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, StoreUnsafe, 16, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Subtract, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, Sum, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector128, ToScalar, 16, 1, {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, {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, {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, {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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, WithElement, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector128, Xor, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|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_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, 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, 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, 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, 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_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, 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, 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) +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_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) +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, 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, 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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, ConditionalSelect, 32, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, ConvertToDouble, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector256, ConvertToInt32, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, ConvertToInt64, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector256, ConvertToSingle, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, ConvertToUInt32, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector256, ConvertToUInt64, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector256, Create, 32, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, CreateScalar, 32, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, CreateScalarUnsafe, 32, 1, {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, Divide, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Dot, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Equals, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_ReturnsPerElementMask) -HARDWARE_INTRINSIC(Vector256, EqualsAll, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, EqualsAny, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, ExtractMostSignificantBits, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Floor, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, get_AllBitsSet, 32, 0, {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_One, 32, 0, {INS_invalid, INS_invalid, INS_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, {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, GetElement, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, GetLower, 32, 1, {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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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_Equality, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(Vector256, op_ExclusiveOr, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, op_Inequality, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(Vector256, op_LeftShift, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, op_Multiply, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, op_OnesComplement, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, op_RightShift, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, op_Subtraction, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, op_UnaryNegation, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, op_UnaryPlus, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, op_UnsignedRightShift, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, ShiftLeft, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, ShiftRightArithmetic, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, ShiftRightLogical, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Shuffle, 32, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Sqrt, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, Store, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, StoreAligned, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, StoreAlignedNonTemporal, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, StoreUnsafe, 32, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, Subtract, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, Sum, 32, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector256, ToScalar, 32, 1, {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, {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, {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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, WithElement, 32, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, WithLower, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, WithUpper, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_AvxOnlyCompatible) -HARDWARE_INTRINSIC(Vector256, Xor, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_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_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, 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, 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, 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_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, 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, 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) +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_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) +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, 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, 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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, ConditionalSelect, 64, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, BitwiseOr, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Ceiling, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Create, 64, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, CreateScalar, 64, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, CreateScalarUnsafe, 64, 1, {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, ConvertToSingle, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector512, ConvertToInt32, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector512, Divide, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Equals, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, EqualsAll, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, EqualsAny, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, ExtractMostSignificantBits, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Floor, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, get_AllBitsSet, 64, 0, {INS_invalid, INS_invalid, INS_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_One, 64, 0, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, GetElement, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector512, GetLower, 64, 1, {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, {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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, 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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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_Equality, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(Vector512, op_ExclusiveOr, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, op_Inequality, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen|HW_Flag_Commutative) -HARDWARE_INTRINSIC(Vector512, op_LeftShift, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, op_Multiply, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, op_OnesComplement, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, op_RightShift, 32, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, op_Subtraction, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, op_UnaryNegation, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, op_UnaryPlus, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, op_UnsignedRightShift, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, ShiftLeft, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, ShiftRightArithmetic, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, ShiftRightLogical, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Shuffle, 64, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Sqrt, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Store, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, StoreAligned, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, StoreAlignedNonTemporal, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, StoreUnsafe, 64, -1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Subtract, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, ToScalar, 64, 1, {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, {INS_invalid, INS_invalid, INS_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, {INS_invalid, INS_invalid, INS_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, WithElement, 64, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_BaseTypeFromFirstArg) -HARDWARE_INTRINSIC(Vector512, WithLower, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, WithUpper, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_SpecialImport|HW_Flag_NoCodeGen) -HARDWARE_INTRINSIC(Vector512, Xor, 64, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Helper, HW_Flag_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_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, 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, 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, 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, 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_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, 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, 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) +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_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) +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, 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(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, 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, 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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // X86Base Intrinsics -HARDWARE_INTRINSIC(X86Base, BitScanForward, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_bsf, INS_bsf, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(X86Base, BitScanReverse, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_bsr, INS_bsr, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(X86Base, DivRem, 0, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_idiv, INS_div, INS_idiv, INS_div, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_BaseTypeFromSecondArg|HW_Flag_MultiReg|HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_RmwIntrinsic) -HARDWARE_INTRINSIC(X86Base, Pause, 0, 0, {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_Other) +HARDWARE_INTRINSIC(X86Base, BitScanForward, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_bsf, INS_bsf, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(X86Base, BitScanReverse, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_bsr, INS_bsr, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(X86Base, DivRem, 0, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_idiv, INS_div, INS_idiv, INS_div, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_BaseTypeFromSecondArg|HW_Flag_MultiReg|HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_RmwIntrinsic) +HARDWARE_INTRINSIC(X86Base, Pause, 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_Other) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // X86Base 64-bit-only Intrinsics -HARDWARE_INTRINSIC(X86Base_X64, BitScanForward, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_bsf, INS_bsf, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(X86Base_X64, BitScanReverse, 0, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_bsr, INS_bsr, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(X86Base_X64, DivRem, 0, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_idiv, INS_div, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_BaseTypeFromSecondArg|HW_Flag_MultiReg|HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_RmwIntrinsic) +HARDWARE_INTRINSIC(X86Base_X64, BitScanForward, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_bsf, INS_bsf, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(X86Base_X64, BitScanReverse, 0, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_bsr, INS_bsr, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(X86Base_X64, DivRem, 0, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_idiv, INS_div, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_BaseTypeFromSecondArg|HW_Flag_MultiReg|HW_Flag_SpecialImport|HW_Flag_SpecialCodeGen|HW_Flag_RmwIntrinsic) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // SSE Intrinsics -HARDWARE_INTRINSIC(SSE, Add, 16, 2, {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) -HARDWARE_INTRINSIC(SSE, AddScalar, 16, 2, {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, {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) -HARDWARE_INTRINSIC(SSE, AndNot, 16, 2, {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_NoFlag) -HARDWARE_INTRINSIC(SSE, CompareEqual, 16, 2, {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, {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, {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, CompareScalarUnorderedEqual, 16, 2, {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) -HARDWARE_INTRINSIC(SSE, CompareGreaterThan, 16, 2, {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_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE, CompareScalarOrderedGreaterThan, 16, 2, {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, CompareScalarGreaterThan, 16, 2, {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_SpecialImport|HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE, CompareScalarUnorderedGreaterThan, 16, 2, {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, CompareGreaterThanOrEqual, 16, 2, {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_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE, CompareScalarOrderedGreaterThanOrEqual, 16, 2, {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, CompareScalarGreaterThanOrEqual, 16, 2, {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_SpecialImport|HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE, CompareScalarUnorderedGreaterThanOrEqual, 16, 2, {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, CompareLessThan, 16, 2, {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_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE, CompareScalarOrderedLessThan, 16, 2, {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, CompareScalarLessThan, 16, 2, {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, CompareScalarUnorderedLessThan, 16, 2, {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, CompareLessThanOrEqual, 16, 2, {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_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE, CompareScalarOrderedLessThanOrEqual, 16, 2, {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, {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, {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, {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, CompareScalarOrderedNotEqual, 16, 2, {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, {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, {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) -HARDWARE_INTRINSIC(SSE, CompareNotGreaterThan, 16, 2, {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_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE, CompareScalarNotGreaterThan, 16, 2, {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_SpecialImport|HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE, CompareNotGreaterThanOrEqual, 16, 2, {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_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE, CompareScalarNotGreaterThanOrEqual, 16, 2, {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_SpecialImport|HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE, CompareNotLessThan, 16, 2, {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_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE, CompareScalarNotLessThan, 16, 2, {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, CompareNotLessThanOrEqual, 16, 2, {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_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE, CompareScalarNotLessThanOrEqual, 16, 2, {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, CompareOrdered, 16, 2, {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_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE, CompareScalarOrdered, 16, 2, {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, CompareUnordered, 16, 2, {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_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE, CompareScalarUnordered, 16, 2, {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, ConvertToInt32, 16, 1, {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, {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, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE, Divide, 16, 2, {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_NoFlag) -HARDWARE_INTRINSIC(SSE, DivideScalar, 16, 2, {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, {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, {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, {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, {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, {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, {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) -HARDWARE_INTRINSIC(SSE, MaxScalar, 16, 2, {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, {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) -HARDWARE_INTRINSIC(SSE, MinScalar, 16, 2, {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, {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, {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, {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, {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, {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) -HARDWARE_INTRINSIC(SSE, MultiplyScalar, 16, 2, {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, {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) -HARDWARE_INTRINSIC(SSE, Prefetch0, 0, 1, {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, {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, {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) -HARDWARE_INTRINSIC(SSE, PrefetchNonTemporal, 0, 1, {INS_invalid, INS_prefetchnta, 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, Reciprocal, 16, 1, {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_NoRMWSemantics|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE, ReciprocalScalar, 16, -1, {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, {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, {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, {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, {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, SqrtScalar, 16, -1, {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, {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, StoreAligned, 16, 2, {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, {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, {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, {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, {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, {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, {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_NoFlag) -HARDWARE_INTRINSIC(SSE, SubtractScalar, 16, 2, {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, {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, {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, {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) +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, 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) +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_NoFlag) +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) +HARDWARE_INTRINSIC(SSE, CompareScalarUnorderedEqual, 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) +HARDWARE_INTRINSIC(SSE, CompareGreaterThan, 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_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(SSE, CompareScalarOrderedGreaterThan, 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, CompareScalarGreaterThan, 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_SpecialImport|HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(SSE, CompareScalarUnorderedGreaterThan, 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, CompareGreaterThanOrEqual, 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_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(SSE, CompareScalarOrderedGreaterThanOrEqual, 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, CompareScalarGreaterThanOrEqual, 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_SpecialImport|HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(SSE, CompareScalarUnorderedGreaterThanOrEqual, 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, CompareLessThan, 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_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(SSE, CompareScalarOrderedLessThan, 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, CompareScalarLessThan, 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, CompareScalarUnorderedLessThan, 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, CompareLessThanOrEqual, 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_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +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, 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) +HARDWARE_INTRINSIC(SSE, CompareNotGreaterThan, 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_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(SSE, CompareScalarNotGreaterThan, 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_SpecialImport|HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(SSE, CompareNotGreaterThanOrEqual, 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_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(SSE, CompareScalarNotGreaterThanOrEqual, 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_SpecialImport|HW_Flag_CopyUpperBits|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(SSE, CompareNotLessThan, 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_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(SSE, CompareScalarNotLessThan, 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, CompareNotLessThanOrEqual, 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_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(SSE, CompareScalarNotLessThanOrEqual, 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, CompareOrdered, 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_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(SSE, CompareScalarOrdered, 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, CompareUnordered, 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_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(SSE, CompareScalarUnordered, 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, 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_cvttss2si, 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_NoFlag) +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) +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) +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) +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) +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) +HARDWARE_INTRINSIC(SSE, PrefetchNonTemporal, 0, 1, false, {INS_invalid, INS_prefetchnta, 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, Reciprocal, 16, 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_NoRMWSemantics|HW_Flag_NoEvexSemantics) +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, 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, 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_NoFlag) +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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // SSE 64-bit-only Intrinsics -HARDWARE_INTRINSIC(SSE_X64, ConvertToInt64, 16, 1, {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|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(SSE_X64, ConvertToInt64WithTruncation, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(SSE_X64, ConvertScalarToVector128Single, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsi2ss64, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_CopyUpperBits|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(SSE_X64, ConvertToInt64, 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|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(SSE_X64, ConvertToInt64WithTruncation, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttss2si, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(SSE_X64, ConvertScalarToVector128Single, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsi2ss64, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_CopyUpperBits|HW_Flag_SpecialCodeGen) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // SSE2 Intrinsics -HARDWARE_INTRINSIC(SSE2, Add, 16, 2, {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) -HARDWARE_INTRINSIC(SSE2, AddSaturate, 16, 2, {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, AddScalar, 16, 2, {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, {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) -HARDWARE_INTRINSIC(SSE2, AndNot, 16, 2, {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_NoFlag) -HARDWARE_INTRINSIC(SSE2, Average, 16, 2, {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, CompareEqual, 16, 2, {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, {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, {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, CompareScalarUnorderedEqual, 16, 2, {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_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2, CompareGreaterThan, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE2, CompareScalarOrderedGreaterThan, 16, 2, {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, {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, {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, {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, CompareScalarOrderedGreaterThanOrEqual, 16, 2, {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, {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, {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, CompareLessThan, 16, 2, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE2, CompareScalarOrderedLessThan, 16, 2, {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, {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, {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, {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, CompareScalarOrderedLessThanOrEqual, 16, 2, {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, {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, {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, {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, {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, CompareScalarNotEqual, 16, 2, {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, {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, CompareNotGreaterThan, 16, 2, {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, {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, {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, {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, {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, {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, {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, CompareScalarNotLessThanOrEqual, 16, 2, {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, {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, CompareScalarOrdered, 16, 2, {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, {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, CompareScalarUnordered, 16, 2, {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, {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, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2, ConvertToUInt32, 16, 1, {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, {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, ConvertScalarToVector128Double, 16, 2, {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, {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, ConvertScalarToVector128Int32, 16, 1, {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, {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, {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, ConvertScalarToVector128Single, 16, 2, {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, {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, {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_NoFlag) -HARDWARE_INTRINSIC(SSE2, DivideScalar, 16, 2, {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, {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, {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) -HARDWARE_INTRINSIC(SSE2, LoadAlignedVector128, 16, 1, {INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_invalid, INS_movapd}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2, LoadFence, 0, 0, {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, LoadHigh, 16, 2, {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, {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, {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, {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, MaskMove, 16, 3, {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, {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) -HARDWARE_INTRINSIC(SSE2, MemoryFence, 0, 0, {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, {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, {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) -HARDWARE_INTRINSIC(SSE2, MinScalar, 16, 2, {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, {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, {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, {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) -HARDWARE_INTRINSIC(SSE2, MultiplyHigh, 16, 2, {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, {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, {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, MultiplyScalar, 16, 2, {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, {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) -HARDWARE_INTRINSIC(SSE2, PackSignedSaturate, 16, 2, {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, {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, {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, {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, ShiftLeftLogical128BitLane, 16, 2, {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, {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, {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, ShiftRightLogical128BitLane, 16, 2, {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, {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, {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, {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, {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, SqrtScalar, 16, -1, {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, {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, StoreAligned, 16, 2, {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, {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, {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, {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, {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, {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, {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_NoFlag) -HARDWARE_INTRINSIC(SSE2, SubtractSaturate, 16, 2, {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, SubtractScalar, 16, 2, {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, {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, {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, {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) +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, 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) +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_NoFlag) +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, 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) +HARDWARE_INTRINSIC(SSE2, CompareScalarUnorderedEqual, 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_BaseTypeFromFirstArg|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2, CompareGreaterThan, 16, 2, true, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +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, 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) +HARDWARE_INTRINSIC(SSE2, CompareLessThan, 16, 2, true, {INS_pcmpgtb, INS_invalid, INS_pcmpgtw, INS_invalid, INS_pcmpgtd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cmppd}, HW_Category_SimpleSIMD, HW_Flag_ReturnsPerElementMask|HW_Flag_NoEvexSemantics) +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, 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, 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, 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, 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, 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, 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_cvttsd2si}, 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, 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, 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, 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_NoFlag) +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) +HARDWARE_INTRINSIC(SSE2, LoadAlignedVector128, 16, 1, true, {INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_movdqa, INS_invalid, INS_movapd}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2, LoadFence, 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, 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, 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) +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) +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) +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, 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) +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, 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, 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, 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, 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_NoFlag) +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, 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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // SSE2 64-bit-only Intrinsics -HARDWARE_INTRINSIC(SSE2_X64, ConvertToInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_invalid, INS_invalid, INS_cvtsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_X64, ConvertToInt64WithTruncation, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_X64, ConvertToUInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2_X64, ConvertScalarToVector128Double, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsi2sd64, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) -HARDWARE_INTRINSIC(SSE2_X64, ConvertScalarToVector128Int64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(SSE2_X64, ConvertScalarToVector128UInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(SSE2_X64, StoreNonTemporal, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movnti, INS_movnti, INS_invalid, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(SSE2_X64, ConvertToInt64, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_invalid, INS_invalid, INS_cvtsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_X64, ConvertToInt64WithTruncation, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvttsd2si}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_X64, ConvertToUInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2_X64, ConvertScalarToVector128Double, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtsi2sd64, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) +HARDWARE_INTRINSIC(SSE2_X64, ConvertScalarToVector128Int64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(SSE2_X64, ConvertScalarToVector128UInt64, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(SSE2_X64, StoreNonTemporal, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movnti, INS_movnti, INS_invalid, INS_invalid}, HW_Category_MemoryStore, HW_Flag_NoRMWSemantics|HW_Flag_SpecialCodeGen|HW_Flag_BaseTypeFromSecondArg) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // SSE3 Intrinsics -HARDWARE_INTRINSIC(SSE3, AddSubtract, 16, 2, {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(SSE3, HorizontalAdd, 16, 2, {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(SSE3, HorizontalSubtract, 16, 2, {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(SSE3, LoadAndDuplicateToVector128, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_lddqu, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movddup}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE3, LoadDquVector128, 16, 1, {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_NoRMWSemantics|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(SSE3, MoveAndDuplicate, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movddup}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE3, MoveHighAndDuplicate, 16, 1, {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_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE3, MoveLowAndDuplicate, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movsldup, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE3, AddSubtract, 16, 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(SSE3, HorizontalAdd, 16, 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(SSE3, HorizontalSubtract, 16, 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(SSE3, LoadAndDuplicateToVector128, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_lddqu, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movddup}, HW_Category_MemoryLoad, HW_Flag_NoRMWSemantics|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(SSE3, LoadDquVector128, 16, 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_NoRMWSemantics|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(SSE3, MoveAndDuplicate, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movddup}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE3, MoveHighAndDuplicate, 16, 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_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE3, MoveLowAndDuplicate, 16, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movsldup, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoRMWSemantics) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // SSSE3 Intrinsics -HARDWARE_INTRINSIC(SSSE3, Abs, 16, 1, {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, {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, HorizontalAdd, 16, 2, {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, {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, {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, {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, {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, {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, {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, Sign, 16, 2, {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(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, 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, 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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // SSE41 Intrinsics -HARDWARE_INTRINSIC(SSE41, Blend, 16, 3, {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, {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, {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, CeilingScalar, 16, -1, {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, {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, {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, {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, {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, {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, {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, {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, FloorScalar, 16, -1, {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, {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) -HARDWARE_INTRINSIC(SSE41, LoadAlignedVector128NonTemporal, 16, 1, {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, {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_NoFlag) -HARDWARE_INTRINSIC(SSE41, Min, 16, 2, {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_NoFlag) -HARDWARE_INTRINSIC(SSE41, MinHorizontal, 16, 1, {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, {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, {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) -HARDWARE_INTRINSIC(SSE41, MultiplyLow, 16, 2, {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_NoFlag) -HARDWARE_INTRINSIC(SSE41, PackUnsignedSaturate, 16, 2, {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, {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, RoundCurrentDirectionScalar, 16, -1, {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, {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, RoundToNearestIntegerScalar, 16, -1, {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, {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, RoundToNegativeInfinityScalar, 16, -1, {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, {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, RoundToPositiveInfinityScalar, 16, -1, {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, {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, RoundToZeroScalar, 16, -1, {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, {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, {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, TestZ, 16, 2, {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, 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, 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, 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) +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_NoFlag) +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_NoFlag) +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) +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_NoFlag) +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, 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, 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, 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, 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, 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) +HARDWARE_INTRINSIC(SSE41, TestZ, 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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // SSE41 64-bit-only Intrinsics -HARDWARE_INTRINSIC(SSE41_X64, Extract, 16, 2, {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, Insert, 16, 3, {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) +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, 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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // SSE42 Intrinsics -HARDWARE_INTRINSIC(SSE42, Crc32, 0, 2, {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, {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, {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, 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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // SSE42 Intrinsics -HARDWARE_INTRINSIC(SSE42_X64, Crc32, 0, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_crc32, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_RmwIntrinsic) +HARDWARE_INTRINSIC(SSE42_X64, Crc32, 0, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_crc32, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_RmwIntrinsic) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // AVX Intrinsics -HARDWARE_INTRINSIC(AVX, Add, 32, 2, {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) -HARDWARE_INTRINSIC(AVX, AddSubtract, 32, 2, {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, {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(AVX, AndNot, 32, 2, {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_NoFlag) -HARDWARE_INTRINSIC(AVX, Blend, 32, 3, {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, {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, {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, BroadcastScalarToVector128, 16, 1, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, CompareScalar, 16, 3, {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, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtpd2dq, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX, ConvertToVector128Single, 32, 1, {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, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_cvtps2dq, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX, ConvertToVector256Single, 32, 1, {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, {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, {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, {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, {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_NoFlag) -HARDWARE_INTRINSIC(AVX, DotProduct, 32, 3, {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, {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, {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, {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, {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, HorizontalAdd, 32, 2, {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, {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, {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, LoadAlignedVector256, 32, 1, {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, {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, {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, {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) -HARDWARE_INTRINSIC(AVX, Min, 32, 2, {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) -HARDWARE_INTRINSIC(AVX, MaskLoad, -1, 2, {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, {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, {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, {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) -HARDWARE_INTRINSIC(AVX, Or, 32, 2, {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) -HARDWARE_INTRINSIC(AVX, Permute, -1, 2, {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, Permute2x128, 32, 3, {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, {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, Reciprocal, 32, 1, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, StoreAligned, 32, 2, {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, {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, {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_NoFlag) -HARDWARE_INTRINSIC(AVX, TestC, -1, 2, {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, {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, {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, {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, {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, {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) +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, 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) +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_NoFlag) +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, 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, 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_invalid}, 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_invalid, 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_NoFlag) +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, 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, 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) +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) +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) +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) +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, 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, 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, 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_NoFlag) +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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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, {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, {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) -HARDWARE_INTRINSIC(AVX2, AddSaturate, 32, 2, {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, {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, {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) -HARDWARE_INTRINSIC(AVX2, AndNot, 32, 2, {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_NoFlag) -HARDWARE_INTRINSIC(AVX2, Average, 32, 2, {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, Blend, -1, 3, {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, {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, {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) -HARDWARE_INTRINSIC(AVX2, BroadcastScalarToVector256, 32, 1, {INS_vpbroadcastb, INS_vpbroadcastb, INS_vpbroadcastw, INS_vpbroadcastw, INS_vpbroadcastd, INS_vpbroadcastd, INS_vpbroadcastq, INS_vpbroadcastq, INS_vbroadcastss, INS_vbroadcastsd}, HW_Category_SIMDScalar, HW_Flag_MaybeMemoryLoad) -HARDWARE_INTRINSIC(AVX2, BroadcastVector128ToVector256, 32, 1, {INS_vbroadcasti128, INS_vbroadcasti128, INS_vbroadcasti128, INS_vbroadcasti128, INS_vbroadcasti128, INS_vbroadcasti128, INS_vbroadcasti128, INS_vbroadcasti128, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX2, CompareEqual, 32, 2, {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, {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, {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, {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, ConvertToInt32, 32, 1, {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, {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, {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) -HARDWARE_INTRINSIC(AVX2, ConvertToVector256Int32, 32, 1, {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_MaybeMemoryLoad) -HARDWARE_INTRINSIC(AVX2, ConvertToVector256Int64, 32, 1, {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_MaybeMemoryLoad) -HARDWARE_INTRINSIC(AVX2, GatherVector128, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpgatherdd, INS_vpgatherdd, INS_vpgatherdq, INS_vpgatherdq, INS_vgatherdps, INS_vgatherdpd}, HW_Category_IMM, HW_Flag_MaybeMemoryLoad|HW_Flag_SpecialCodeGen|HW_Flag_NoContainment|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AVX2, GatherVector256, 32, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpgatherdd, INS_vpgatherdd, INS_vpgatherdq, INS_vpgatherdq, INS_vgatherdps, INS_vgatherdpd}, HW_Category_IMM, HW_Flag_MaybeMemoryLoad|HW_Flag_SpecialCodeGen|HW_Flag_NoContainment|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AVX2, GatherMaskVector128, 16, 5, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpgatherdd, INS_vpgatherdd, INS_vpgatherdq, INS_vpgatherdq, INS_vgatherdps, INS_vgatherdpd}, HW_Category_IMM, HW_Flag_MaybeMemoryLoad|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AVX2, GatherMaskVector256, 32, 5, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpgatherdd, INS_vpgatherdd, INS_vpgatherdq, INS_vpgatherdq, INS_vgatherdps, INS_vgatherdpd}, HW_Category_IMM, HW_Flag_MaybeMemoryLoad|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AVX2, HorizontalAdd, 32, 2, {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(AVX2, HorizontalAddSaturate, 32, 2, {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, {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, {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, {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, LoadAlignedVector256NonTemporal, 32, 1, {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, {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, {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, {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) -HARDWARE_INTRINSIC(AVX2, Min, 32, 2, {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) -HARDWARE_INTRINSIC(AVX2, MoveMask, 32, 1, {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, {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) -HARDWARE_INTRINSIC(AVX2, MultipleSumAbsoluteDifferences, 32, 3, {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, {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, {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, {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, {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) -HARDWARE_INTRINSIC(AVX2, Or, 32, 2, {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) -HARDWARE_INTRINSIC(AVX2, Permute2x128, 32, 3, {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, {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, {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, {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, {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, {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, ShiftLeftLogical128BitLane, 32, 2, {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, {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_NoFlag) -HARDWARE_INTRINSIC(AVX2, ShiftRightArithmetic, 32, 2, {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, {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_NoFlag) -HARDWARE_INTRINSIC(AVX2, ShiftRightLogical, 32, 2, {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, ShiftRightLogical128BitLane, 32, 2, {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, {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_NoFlag) -HARDWARE_INTRINSIC(AVX2, Shuffle, 32, 2, {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, {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, {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, Sign, 32, 2, {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, {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, {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_NoFlag) -HARDWARE_INTRINSIC(AVX2, SubtractSaturate, 32, 2, {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, {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, {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, {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) +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) +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_NoFlag) +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, 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) +HARDWARE_INTRINSIC(AVX2, BroadcastScalarToVector256, 32, 1, true, {INS_vpbroadcastb, INS_vpbroadcastb, INS_vpbroadcastw, INS_vpbroadcastw, INS_vpbroadcastd, INS_vpbroadcastd, INS_vpbroadcastq, INS_vpbroadcastq, INS_vbroadcastss, INS_vbroadcastsd}, HW_Category_SIMDScalar, HW_Flag_MaybeMemoryLoad) +HARDWARE_INTRINSIC(AVX2, BroadcastVector128ToVector256, 32, 1, false, {INS_vbroadcasti128, INS_vbroadcasti128, INS_vbroadcasti128, INS_vbroadcasti128, INS_vbroadcasti128, INS_vbroadcasti128, INS_vbroadcasti128, INS_vbroadcasti128, INS_invalid, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoFlag) +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, 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) +HARDWARE_INTRINSIC(AVX2, ConvertToVector256Int32, 32, 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_MaybeMemoryLoad) +HARDWARE_INTRINSIC(AVX2, ConvertToVector256Int64, 32, 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_MaybeMemoryLoad) +HARDWARE_INTRINSIC(AVX2, GatherVector128, 16, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpgatherdd, INS_vpgatherdd, INS_vpgatherdq, INS_vpgatherdq, INS_vgatherdps, INS_vgatherdpd}, HW_Category_IMM, HW_Flag_MaybeMemoryLoad|HW_Flag_SpecialCodeGen|HW_Flag_NoContainment|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AVX2, GatherVector256, 32, 3, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpgatherdd, INS_vpgatherdd, INS_vpgatherdq, INS_vpgatherdq, INS_vgatherdps, INS_vgatherdpd}, HW_Category_IMM, HW_Flag_MaybeMemoryLoad|HW_Flag_SpecialCodeGen|HW_Flag_NoContainment|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AVX2, GatherMaskVector128, 16, 5, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpgatherdd, INS_vpgatherdd, INS_vpgatherdq, INS_vpgatherdq, INS_vgatherdps, INS_vgatherdpd}, HW_Category_IMM, HW_Flag_MaybeMemoryLoad|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AVX2, GatherMaskVector256, 32, 5, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpgatherdd, INS_vpgatherdd, INS_vpgatherdq, INS_vpgatherdq, INS_vgatherdps, INS_vgatherdpd}, HW_Category_IMM, HW_Flag_MaybeMemoryLoad|HW_Flag_SpecialCodeGen|HW_Flag_SpecialImport|HW_Flag_NoContainment|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AVX2, HorizontalAdd, 32, 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(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, 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) +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) +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) +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) +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) +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, 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_NoFlag) +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_NoFlag) +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, 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_NoFlag) +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, 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_NoFlag) +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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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, {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, 2, {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) -HARDWARE_INTRINSIC(AVX512F, AlignRight32, 64, 3, {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, {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, {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) -HARDWARE_INTRINSIC(AVX512F, AndNot, 64, 2, {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_NoFlag) -HARDWARE_INTRINSIC(AVX512F, BroadcastScalarToVector512, 64, 1, {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, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vbroadcasti128, INS_vbroadcasti128, INS_invalid, INS_invalid, INS_vbroadcastf128, INS_invalid}, HW_Category_MemoryLoad, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512F, BroadcastVector256ToVector512, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vbroadcasti64x4, INS_vbroadcasti64x4, INS_invalid, INS_vbroadcastf64x4}, HW_Category_MemoryLoad, HW_Flag_NoFlag) -HARDWARE_INTRINSIC(AVX512F, ConvertScalarToVector128Double, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtusi2sd32, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(AVX512F, ConvertScalarToVector128Single, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtusi2ss32, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(AVX512F, ConvertToUInt32, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtss2usi, INS_vcvtsd2usi}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AVX512F, ConvertToUInt32WithTruncation, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttss2usi, INS_vcvttsd2usi}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AVX512F, ConvertToVector128Byte, 64, 1, {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, ConvertToVector128ByteWithSaturation, 64, 1, {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, ConvertToVector128Int16, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovqw, INS_vpmovqw, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AVX512F, ConvertToVector128Int16WithSaturation, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovsqw, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AVX512F, ConvertToVector128SByte, 64, 1, {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, ConvertToVector128SByteWithSaturation, 64, 1, {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, ConvertToVector128UInt16, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovqw, INS_vpmovqw, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AVX512F, ConvertToVector128UInt16WithSaturation, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovusqw, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AVX512F, ConvertToVector256Int16, 64, 1, {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, ConvertToVector256Int16WithSaturation, 64, 1, {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, {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) -HARDWARE_INTRINSIC(AVX512F, ConvertToVector256Int32WithSaturation, 64, 1, {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, {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, {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(AVX512F, ConvertToVector256UInt16, 64, 1, {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, {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, {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) -HARDWARE_INTRINSIC(AVX512F, ConvertToVector256UInt32WithSaturation, 64, 1, {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, {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, {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, {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) -HARDWARE_INTRINSIC(AVX512F, ConvertToVector512Int32WithTruncation, 64, 1, {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, ConvertToVector512Int64, 64, 1, {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, {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) -HARDWARE_INTRINSIC(AVX512F, ConvertToVector512UInt32, 64, 1, {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) -HARDWARE_INTRINSIC(AVX512F, ConvertToVector512UInt32WithTruncation, 64, 1, {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, ConvertToVector512UInt64, 64, 1, {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, 2, {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_NoFlag) -HARDWARE_INTRINSIC(AVX512F, DuplicateEvenIndexed, 64, 1, {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, {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, {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, {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, {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, FixupScalar, 16, 4, {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, 3, {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(AVX512F, FusedMultiplyAddNegated, 64, 3, {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(AVX512F, FusedMultiplyAddSubtract, 64, 3, {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(AVX512F, FusedMultiplySubtract, 64, 3, {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(AVX512F, FusedMultiplySubtractAdd, 64, 3, {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(AVX512F, FusedMultiplySubtractNegated, 64, 3, {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(AVX512F, GetExponent, 64, 1, {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, GetExponentScalar, 16, -1, {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, {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, GetMantissaScalar, 16, -1, {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, {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, {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, LoadAlignedVector512, 64, 1, {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, {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, {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, {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) -HARDWARE_INTRINSIC(AVX512F, Min, 64, 2, {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) -HARDWARE_INTRINSIC(AVX512F, Multiply, 64, 2, {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) -HARDWARE_INTRINSIC(AVX512F, MultiplyLow, 64, 2, {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) -HARDWARE_INTRINSIC(AVX512F, Or, 64, 2, {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) -HARDWARE_INTRINSIC(AVX512F, Permute2x64, 64, 2, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, Reciprocal14Scalar, 16, -1, {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, {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, ReciprocalSqrt14Scalar, 16, -1, {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, {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, {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, {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, {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, {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, RoundScaleScalar, 16, -1, {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, 2, {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, ScaleScalar, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vscalefss, INS_vscalefsd}, HW_Category_SimpleSIMD, HW_Flag_CopyUpperBits) -HARDWARE_INTRINSIC(AVX512F, ShiftLeftLogical, 64, 2, {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, {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_NoFlag) -HARDWARE_INTRINSIC(AVX512F, ShiftRightArithmetic, 64, 2, {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, {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_NoFlag) -HARDWARE_INTRINSIC(AVX512F, ShiftRightLogical, 64, 2, {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, {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_NoFlag) -HARDWARE_INTRINSIC(AVX512F, Shuffle, 64, -1, {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, {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, {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(AVX512F, Store, 64, 2, {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, StoreAligned, 64, 2, {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, {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, 2, {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_NoFlag) -HARDWARE_INTRINSIC(AVX512F, UnpackHigh, 64, 2, {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, {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, {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, {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) +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, 2, true, {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) +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) +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_NoFlag) +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_MemoryLoad, HW_Flag_NoFlag) +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_MemoryLoad, HW_Flag_NoFlag) +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_Commutative|HW_Flag_ReturnsPerElementMask|HW_Flag_NoCodeGen) +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_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_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_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_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_Commutative|HW_Flag_ReturnsPerElementMask|HW_Flag_NoCodeGen) +HARDWARE_INTRINSIC(AVX512F, ConvertScalarToVector128Double, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtusi2sd32, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(AVX512F, ConvertScalarToVector128Single, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtusi2ss32, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_CopyUpperBits) +HARDWARE_INTRINSIC(AVX512F, ConvertToUInt32, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtss2usi, INS_vcvtsd2usi}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AVX512F, ConvertToUInt32WithTruncation, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttss2usi, INS_vcvttsd2usi}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AVX512F, ConvertToVector128Byte, 64, 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, ConvertToVector128ByteWithSaturation, 64, 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, ConvertToVector128Int16, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovqw, INS_vpmovqw, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AVX512F, ConvertToVector128Int16WithSaturation, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovsqw, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AVX512F, ConvertToVector128SByte, 64, 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, ConvertToVector128SByteWithSaturation, 64, 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, ConvertToVector128UInt16, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovqw, INS_vpmovqw, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AVX512F, ConvertToVector128UInt16WithSaturation, 64, 1, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vpmovusqw, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AVX512F, ConvertToVector256Int16, 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, 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, true, {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) +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) +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, true, {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) +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, true, {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) +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, 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, true, {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) +HARDWARE_INTRINSIC(AVX512F, ConvertToVector512UInt32, 64, 1, true, {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) +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, 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, 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_NoFlag) +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, 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, 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(AVX512F, FusedMultiplyAddNegated, 64, 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(AVX512F, FusedMultiplyAddSubtract, 64, 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(AVX512F, FusedMultiplySubtract, 64, 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(AVX512F, FusedMultiplySubtractAdd, 64, 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(AVX512F, FusedMultiplySubtractNegated, 64, 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(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, 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, 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, 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) +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) +HARDWARE_INTRINSIC(AVX512F, Multiply, 64, 2, true, {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) +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) +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) +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, 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, 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, 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, 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, ScaleScalar, 16, 2, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vscalefss, INS_vscalefsd}, HW_Category_SimpleSIMD, HW_Flag_CopyUpperBits) +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_NoFlag) +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_NoFlag) +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_NoFlag) +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, 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(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, 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, 2, true, {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_NoFlag) +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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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, {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, {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, {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, {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) -HARDWARE_INTRINSIC(AVX512F_VL, Min, -1, 2, {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) -HARDWARE_INTRINSIC(AVX512F_VL, ConvertToVector128Byte, -1, 1, {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, {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, {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, ConvertToVector128Int16, -1, 1, {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, {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, {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, {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, {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, {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, {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, ConvertToVector128UInt16, -1, 1, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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_NoFlag) -HARDWARE_INTRINSIC(AVX512F_VL, Shuffle2x128, 32, 3, {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, {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, 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) +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) +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_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_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_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_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_Commutative|HW_Flag_ReturnsPerElementMask|HW_Flag_NoCodeGen) +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, 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, 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_NoFlag) +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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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.X64 Intrinsics -HARDWARE_INTRINSIC(AVX512F_X64, ConvertScalarToVector128Double, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtusi2sd64, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_CopyUpperBits|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AVX512F_X64, ConvertScalarToVector128Single, 16, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtusi2ss64, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_CopyUpperBits|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AVX512F_X64, ConvertToUInt64, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtss2usi, INS_vcvtsd2usi}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) -HARDWARE_INTRINSIC(AVX512F_X64, ConvertToUInt64WithTruncation, 16, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttss2usi, INS_vcvttsd2usi}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AVX512F_X64, ConvertScalarToVector128Double, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtusi2sd64, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_CopyUpperBits|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AVX512F_X64, ConvertScalarToVector128Single, 16, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtusi2ss64, INS_invalid, INS_invalid}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromSecondArg|HW_Flag_CopyUpperBits|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AVX512F_X64, ConvertToUInt64, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvtss2usi, INS_vcvtsd2usi}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) +HARDWARE_INTRINSIC(AVX512F_X64, ConvertToUInt64WithTruncation, 16, 1, true, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_vcvttss2usi, INS_vcvttsd2usi}, HW_Category_SIMDScalar, HW_Flag_BaseTypeFromFirstArg|HW_Flag_SpecialCodeGen) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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 Intrinsics -HARDWARE_INTRINSIC(AVX512BW, Abs, 64, 1, {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, {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, {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, {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, {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, BroadcastScalarToVector512, 64, 1, {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, ConvertToVector256Byte, 64, 1, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, ShiftLeftLogical128BitLane, 64, 2, {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, {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, {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, {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, {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, ShiftRightLogical128BitLane, 64, 2, {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, {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, {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, {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, {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, {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, {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, {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, SumAbsoluteDifferences, 64, 2, {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, {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, {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, {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, 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, 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_Commutative|HW_Flag_ReturnsPerElementMask|HW_Flag_NoCodeGen) +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_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_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_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_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_Commutative|HW_Flag_ReturnsPerElementMask|HW_Flag_NoCodeGen) +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, 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, 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, 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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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, ConvertToVector128Byte, -1, 1, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, 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_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_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_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_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_Commutative|HW_Flag_ReturnsPerElementMask|HW_Flag_NoCodeGen) +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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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, {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, {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_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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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, {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, {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_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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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, {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, {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_NoFlag) -HARDWARE_INTRINSIC(AVX512DQ, BroadcastPairScalarToVector512, 64, 1, {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, {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, {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, {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, ConvertToVector512Double, 64, 1, {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, ConvertToVector512Int64, 64, 1, {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, ConvertToVector512Int64WithTruncation, 64, 1, {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, {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, ConvertToVector512UInt64WithTruncation, 64, 1, {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, {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, {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, {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, {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, {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) -HARDWARE_INTRINSIC(AVX512DQ, Or, 64, 2, {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) -HARDWARE_INTRINSIC(AVX512DQ, Range, 64, 3, {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, RangeScalar, 16, 3, {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, {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, ReduceScalar, 16, -1, {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, {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) +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_NoFlag) +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, 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, ConvertToVector512Double, 64, 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, ConvertToVector512Int64, 64, 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, 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, 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, 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) +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) +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, 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, 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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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.VL Intrinsics -HARDWARE_INTRINSIC(AVX512DQ_VL, BroadcastPairScalarToVector128, 16, 1, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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) +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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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, {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, {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) +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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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, {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, {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, {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, {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) +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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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, {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, {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_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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // AES Intrinsics -HARDWARE_INTRINSIC(AES, Decrypt, 16, 2, {INS_invalid, INS_aesdec, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AES, DecryptLast, 16, 2, {INS_invalid, INS_aesdeclast, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AES, Encrypt, 16, 2, {INS_invalid, INS_aesenc, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AES, EncryptLast, 16, 2, {INS_invalid, INS_aesenclast, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AES, InverseMixColumns, 16, 1, {INS_invalid, INS_aesimc, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AES, KeygenAssist, 16, 2, {INS_invalid, INS_aeskeygenassist, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AES, Decrypt, 16, 2, false, {INS_invalid, INS_aesdec, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AES, DecryptLast, 16, 2, false, {INS_invalid, INS_aesdeclast, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AES, Encrypt, 16, 2, false, {INS_invalid, INS_aesenc, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AES, EncryptLast, 16, 2, false, {INS_invalid, INS_aesenclast, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AES, InverseMixColumns, 16, 1, false, {INS_invalid, INS_aesimc, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_SimpleSIMD, HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(AES, KeygenAssist, 16, 2, false, {INS_invalid, INS_aeskeygenassist, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_NoEvexSemantics) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // BMI1 Intrinsics -HARDWARE_INTRINSIC(BMI1, AndNot, 0, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andn, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(BMI1, ExtractLowestSetBit, 0, 1, {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, {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, {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, {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, {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, AndNot, 0, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andn, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoEvexSemantics) +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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // BMI1 Intrinsics -HARDWARE_INTRINSIC(BMI1_X64, AndNot, 0, 2, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andn, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(BMI1_X64, ExtractLowestSetBit, 0, 1, {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, {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, {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, {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, {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, AndNot, 0, 2, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_andn, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Scalar, HW_Flag_NoFloatingPointUsed|HW_Flag_NoEvexSemantics) +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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // BMI2 Intrinsics -HARDWARE_INTRINSIC(BMI2, ParallelBitDeposit, 0, 2, {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, {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, {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, {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, 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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // BMI2 Intrinsics -HARDWARE_INTRINSIC(BMI2_X64, ParallelBitDeposit, 0, 2, {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, {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, {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, {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, 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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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, {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, {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, {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, {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, {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, {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, {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, {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, {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, {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) +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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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, {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_MultiIns) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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, {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_MultiIns) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // PCLMULQDQ Intrinsics -HARDWARE_INTRINSIC(PCLMULQDQ, CarrylessMultiply, 16, 3, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pclmulqdq, INS_pclmulqdq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(PCLMULQDQ, CarrylessMultiply, 16, 3, false, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_pclmulqdq, INS_pclmulqdq, INS_invalid, INS_invalid}, HW_Category_IMM, HW_Flag_FullRangeIMM|HW_Flag_NoEvexSemantics) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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, PopCount, 0, 1, {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_MultiIns) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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, {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_MultiIns) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // X86Serialize Intrinsics -HARDWARE_INTRINSIC(X86Serialize, Serialize, 0, 0, {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(X86Serialize, Serialize, 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) // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** -// ISA Function name SIMD size NumArg Instructions Category Flags -// {TYP_BYTE, TYP_UBYTE, TYP_SHORT, TYP_USHORT, TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG, TYP_FLOAT, TYP_DOUBLE} +// 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} // *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** // Special intrinsics that are generated during lowering -HARDWARE_INTRINSIC(SSE, COMISS, 16, 2, {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_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE, UCOMISS, 16, 2, {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_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2, COMISD, 16, 2, {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_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE2, UCOMISD, 16, 2, {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_NoRMWSemantics) -HARDWARE_INTRINSIC(SSE41, PTEST, 16, 2, {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_NoRMWSemantics|HW_Flag_NoEvexSemantics) -HARDWARE_INTRINSIC(AVX, PTEST, 0, 2, {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_NoRMWSemantics|HW_Flag_NoEvexSemantics) +HARDWARE_INTRINSIC(SSE, COMISS, 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_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE, UCOMISS, 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_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2, COMISD, 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_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE2, UCOMISD, 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_NoRMWSemantics) +HARDWARE_INTRINSIC(SSE41, PTEST, 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_NoRMWSemantics|HW_Flag_NoEvexSemantics) +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_movd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_NoContainment) -HARDWARE_INTRINSIC(AVX512F, MoveMaskSpecial, 64, 1, {INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_movd, INS_invalid, INS_invalid, INS_invalid, INS_invalid, INS_invalid}, HW_Category_Special, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoContainment|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(AVX512F, CompareEqualSpecial, 64, 2, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_Special, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoContainment|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(AVX512F, CompareGreaterThanOrEqualSpecial, 64, 2, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_Special, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoContainment|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(AVX512F, CompareGreaterThanSpecial, 64, 2, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_Special, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoContainment|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(AVX512F, CompareLessThanOrEqualSpecial, 64, 2, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_Special, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoContainment|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(AVX512F, CompareLessThanSpecial, 64, 2, {INS_vpcmpb, INS_vpcmpub, INS_vpcmpw, INS_vpcmpuw, INS_vpcmpd, INS_vpcmpud, INS_vpcmpq, INS_vpcmpuq, INS_vcmpps, INS_vcmppd}, HW_Category_Special, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoContainment|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(AVX512F, MoveMaskToVectorSpecial, 64, 1, {INS_vpmovm2b, INS_vpmovm2b, INS_vpmovm2w, INS_vpmovm2w, INS_vpmovm2d, INS_vpmovm2d, INS_vpmovm2q, INS_vpmovm2q, INS_vpmovm2d, INS_vpmovm2q}, HW_Category_Special, HW_Flag_BaseTypeFromFirstArg|HW_Flag_NoContainment|HW_Flag_SpecialCodeGen|HW_Flag_NoRMWSemantics) -HARDWARE_INTRINSIC(AVX512F, KORTEST, 0, 1, {INS_kortestq, INS_kortestq, INS_kortestd, INS_kortestd, INS_kortestw, INS_kortestw, INS_kortestb, INS_kortestb, INS_kortestw, INS_kortestb}, HW_Category_Special, HW_Flag_NoRMWSemantics) +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) +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) +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_ReturnsPerElementMask) +HARDWARE_INTRINSIC(AVX512F, MoveMaskSpecial, -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) #endif // FEATURE_HW_INTRINSIC diff --git a/src/coreclr/jit/hwintrinsicxarch.cpp b/src/coreclr/jit/hwintrinsicxarch.cpp index 379509a17180e6..dadabaddbb9491 100644 --- a/src/coreclr/jit/hwintrinsicxarch.cpp +++ b/src/coreclr/jit/hwintrinsicxarch.cpp @@ -553,6 +553,302 @@ bool HWIntrinsicInfo::isScalarIsa(CORINFO_InstructionSet isa) } } +//------------------------------------------------------------------------ +// lookupIval: Gets a the implicit immediate value for the given intrinsic +// +// Arguments: +// comp - The compiler +// id - The intrinsic for which to get the ival +// simdBaseType - The base type for the intrinsic +// +// Return Value: +// The immediate value for the given intrinsic or -1 if none exists +int HWIntrinsicInfo::lookupIval(Compiler* comp, NamedIntrinsic id, var_types simdBaseType) +{ + switch (id) + { + case NI_SSE_CompareEqual: + case NI_SSE_CompareScalarEqual: + case NI_SSE2_CompareEqual: + case NI_SSE2_CompareScalarEqual: + case NI_AVX_CompareEqual: + case NI_AVX512F_CompareEqualMask: + { + if (varTypeIsFloating(simdBaseType)) + { + return static_cast(FloatComparisonMode::OrderedEqualNonSignaling); + } + else + { + // We can emit `vpcmpeqb`, `vpcmpeqw`, `vpcmpeqd`, or `vpcmpeqq` + } + break; + } + + case NI_SSE_CompareGreaterThan: + case NI_SSE_CompareScalarGreaterThan: + case NI_SSE2_CompareGreaterThan: + case NI_SSE2_CompareScalarGreaterThan: + case NI_AVX_CompareGreaterThan: + case NI_AVX512F_CompareGreaterThanMask: + { + 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. + + assert(id != NI_AVX_CompareGreaterThan); + return static_cast(FloatComparisonMode::OrderedLessThanSignaling); + } + else if ((id == NI_AVX512F_CompareGreaterThanMask) && varTypeIsUnsigned(simdBaseType)) + { + // TODO-XARCH-CQ: Allow the other integer paths to use the EVEX encoding + return static_cast(IntComparisonMode::GreaterThan); + } + break; + } + + case NI_SSE_CompareLessThan: + case NI_SSE_CompareScalarLessThan: + case NI_SSE2_CompareLessThan: + case NI_SSE2_CompareScalarLessThan: + case NI_AVX_CompareLessThan: + case NI_AVX512F_CompareLessThanMask: + { + if (varTypeIsFloating(simdBaseType)) + { + return static_cast(FloatComparisonMode::OrderedLessThanSignaling); + } + else if (id == NI_AVX512F_CompareLessThanMask) + { + // TODO-XARCH-CQ: Allow the other integer paths to use the EVEX encoding + return static_cast(IntComparisonMode::LessThan); + } + break; + } + + case NI_SSE_CompareGreaterThanOrEqual: + case NI_SSE_CompareScalarGreaterThanOrEqual: + case NI_SSE2_CompareGreaterThanOrEqual: + case NI_SSE2_CompareScalarGreaterThanOrEqual: + case NI_AVX_CompareGreaterThanOrEqual: + case NI_AVX512F_CompareGreaterThanOrEqualMask: + { + 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. + + assert(id != NI_AVX_CompareGreaterThanOrEqual); + return static_cast(FloatComparisonMode::OrderedLessThanOrEqualSignaling); + } + else + { + assert(id == NI_AVX512F_CompareGreaterThanOrEqualMask); + return static_cast(IntComparisonMode::GreaterThanOrEqual); + } + break; + } + + case NI_SSE_CompareLessThanOrEqual: + case NI_SSE_CompareScalarLessThanOrEqual: + case NI_SSE2_CompareLessThanOrEqual: + case NI_SSE2_CompareScalarLessThanOrEqual: + case NI_AVX_CompareLessThanOrEqual: + case NI_AVX512F_CompareLessThanOrEqualMask: + { + if (varTypeIsFloating(simdBaseType)) + { + return static_cast(FloatComparisonMode::OrderedLessThanOrEqualSignaling); + } + else + { + assert(id == NI_AVX512F_CompareLessThanOrEqualMask); + return static_cast(IntComparisonMode::LessThanOrEqual); + } + break; + } + + case NI_SSE_CompareNotEqual: + case NI_SSE_CompareScalarNotEqual: + case NI_SSE2_CompareNotEqual: + case NI_SSE2_CompareScalarNotEqual: + case NI_AVX_CompareNotEqual: + case NI_AVX512F_CompareNotEqualMask: + { + if (varTypeIsFloating(simdBaseType)) + { + return static_cast(FloatComparisonMode::UnorderedNotEqualNonSignaling); + } + else + { + assert(id == NI_AVX512F_CompareNotEqualMask); + return static_cast(IntComparisonMode::NotEqual); + } + break; + } + + case NI_SSE_CompareNotGreaterThan: + case NI_SSE_CompareScalarNotGreaterThan: + case NI_SSE2_CompareNotGreaterThan: + case NI_SSE2_CompareScalarNotGreaterThan: + case NI_AVX_CompareNotGreaterThan: + { + assert(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. + + assert(id != NI_AVX_CompareNotGreaterThan); + return static_cast(FloatComparisonMode::UnorderedNotLessThanSignaling); + } + + case NI_SSE_CompareNotLessThan: + case NI_SSE_CompareScalarNotLessThan: + case NI_SSE2_CompareNotLessThan: + case NI_SSE2_CompareScalarNotLessThan: + case NI_AVX_CompareNotLessThan: + { + assert(varTypeIsFloating(simdBaseType)); + return static_cast(FloatComparisonMode::UnorderedNotLessThanSignaling); + } + + case NI_SSE_CompareNotGreaterThanOrEqual: + case NI_SSE_CompareScalarNotGreaterThanOrEqual: + case NI_SSE2_CompareNotGreaterThanOrEqual: + case NI_SSE2_CompareScalarNotGreaterThanOrEqual: + case NI_AVX_CompareNotGreaterThanOrEqual: + { + assert(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. + + assert(id != NI_AVX_CompareNotGreaterThanOrEqual); + return static_cast(FloatComparisonMode::UnorderedNotLessThanOrEqualSignaling); + } + + case NI_SSE_CompareNotLessThanOrEqual: + case NI_SSE_CompareScalarNotLessThanOrEqual: + case NI_SSE2_CompareNotLessThanOrEqual: + case NI_SSE2_CompareScalarNotLessThanOrEqual: + case NI_AVX_CompareNotLessThanOrEqual: + { + assert(varTypeIsFloating(simdBaseType)); + return static_cast(FloatComparisonMode::UnorderedNotLessThanOrEqualSignaling); + } + + case NI_SSE_CompareOrdered: + case NI_SSE_CompareScalarOrdered: + case NI_SSE2_CompareOrdered: + case NI_SSE2_CompareScalarOrdered: + case NI_AVX_CompareOrdered: + { + assert(varTypeIsFloating(simdBaseType)); + return static_cast(FloatComparisonMode::OrderedNonSignaling); + } + + case NI_SSE_CompareUnordered: + case NI_SSE_CompareScalarUnordered: + case NI_SSE2_CompareUnordered: + case NI_SSE2_CompareScalarUnordered: + case NI_AVX_CompareUnordered: + { + assert(varTypeIsFloating(simdBaseType)); + return static_cast(FloatComparisonMode::UnorderedNonSignaling); + } + + case NI_SSE41_Ceiling: + case NI_SSE41_CeilingScalar: + case NI_AVX_Ceiling: + { + FALLTHROUGH; + } + + case NI_SSE41_RoundToPositiveInfinity: + case NI_SSE41_RoundToPositiveInfinityScalar: + case NI_AVX_RoundToPositiveInfinity: + { + assert(varTypeIsFloating(simdBaseType)); + return static_cast(FloatRoundingMode::ToPositiveInfinity); + } + + case NI_SSE41_Floor: + case NI_SSE41_FloorScalar: + case NI_AVX_Floor: + { + FALLTHROUGH; + } + + case NI_SSE41_RoundToNegativeInfinity: + case NI_SSE41_RoundToNegativeInfinityScalar: + case NI_AVX_RoundToNegativeInfinity: + { + assert(varTypeIsFloating(simdBaseType)); + return static_cast(FloatRoundingMode::ToNegativeInfinity); + } + + case NI_SSE41_RoundCurrentDirection: + case NI_SSE41_RoundCurrentDirectionScalar: + case NI_AVX_RoundCurrentDirection: + { + assert(varTypeIsFloating(simdBaseType)); + return static_cast(FloatRoundingMode::CurrentDirection); + } + + case NI_SSE41_RoundToNearestInteger: + case NI_SSE41_RoundToNearestIntegerScalar: + case NI_AVX_RoundToNearestInteger: + { + assert(varTypeIsFloating(simdBaseType)); + return static_cast(FloatRoundingMode::ToNearestInteger); + } + + case NI_SSE41_RoundToZero: + case NI_SSE41_RoundToZeroScalar: + case NI_AVX_RoundToZero: + { + assert(varTypeIsFloating(simdBaseType)); + return static_cast(FloatRoundingMode::ToZero); + } + + default: + { + break; + } + } + + return -1; +} + //------------------------------------------------------------------------ // impNonConstFallback: convert certain SSE2/AVX2 shift intrinsic to its semantic alternative when the imm-arg is // not a compile-time constant @@ -783,10 +1079,8 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, return impSpecialIntrinsic(NI_Vector128_ToVector256, clsHnd, method, sig, simdBaseJitType, retType, simdSize); } - else + else if (vectorTByteLength == XMM_REGSIZE_BYTES) { - assert(vectorTByteLength == XMM_REGSIZE_BYTES); - // We fold away the cast here, as it only exists to satisfy // the type system. It is safe to do this here since the retNode type // and the signature return type are both the same TYP_SIMD. @@ -795,6 +1089,10 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, SetOpLclRelatedToSIMDIntrinsic(retNode); assert(retNode->gtType == getSIMDTypeForSize(getSIMDTypeSizeInBytes(sig->retTypeSigClass))); } + else + { + assert(vectorTByteLength == 0); + } break; } @@ -919,10 +1217,8 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, break; } - else + else if (vectorTByteLength == XMM_REGSIZE_BYTES) { - assert(vectorTByteLength == XMM_REGSIZE_BYTES); - if (compExactlyDependsOn(InstructionSet_AVX)) { // We support Vector256 but Vector is only 16-bytes, so we should @@ -941,6 +1237,10 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, } } } + else + { + assert(vectorTByteLength == 0); + } break; } @@ -969,10 +1269,8 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, } break; } - else + else if (vectorTByteLength == XMM_REGSIZE_BYTES) { - assert(vectorTByteLength == XMM_REGSIZE_BYTES); - if (compExactlyDependsOn(InstructionSet_AVX512F)) { // We support Vector512 but Vector is only 16-bytes, so we should @@ -991,6 +1289,10 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, } } } + else + { + assert(vectorTByteLength == 0); + } break; } @@ -2865,10 +3167,9 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, // These intrinsics are "special import" because the non-AVX path isn't directly // hardware supported. Instead, they start with "swapped operands" and we fix that here. - FloatComparisonMode comparison = - static_cast(HWIntrinsicInfo::lookupIval(intrinsic, true)); - retNode = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, op2, gtNewIconNode(static_cast(comparison)), - NI_AVX_CompareScalar, simdBaseJitType, simdSize); + int ival = HWIntrinsicInfo::lookupIval(this, intrinsic, simdBaseType); + retNode = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, op2, gtNewIconNode(ival), NI_AVX_CompareScalar, + simdBaseJitType, simdSize); } else { @@ -2925,10 +3226,9 @@ GenTree* Compiler::impSpecialIntrinsic(NamedIntrinsic intrinsic, // These intrinsics are "special import" because the non-AVX path isn't directly // hardware supported. Instead, they start with "swapped operands" and we fix that here. - FloatComparisonMode comparison = - static_cast(HWIntrinsicInfo::lookupIval(intrinsic, true)); - retNode = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, op2, gtNewIconNode(static_cast(comparison)), - NI_AVX_CompareScalar, simdBaseJitType, simdSize); + int ival = HWIntrinsicInfo::lookupIval(this, intrinsic, simdBaseType); + retNode = gtNewSimdHWIntrinsicNode(TYP_SIMD16, op1, op2, gtNewIconNode(ival), NI_AVX_CompareScalar, + simdBaseJitType, simdSize); } else { diff --git a/src/coreclr/jit/importercalls.cpp b/src/coreclr/jit/importercalls.cpp index 7f55bdd92ef8d7..4afb8c55535495 100644 --- a/src/coreclr/jit/importercalls.cpp +++ b/src/coreclr/jit/importercalls.cpp @@ -5584,25 +5584,25 @@ void Compiler::addFatPointerCandidate(GenTreeCall* call) // pickGDV: Use profile information to pick a GDV candidate for a call site. // // Arguments: -// call - the call -// ilOffset - exact IL offset of the call -// isInterface - whether or not the call target is defined on an interface -// classGuess - [out] the class to guess for (mutually exclusive with methodGuess) -// methodGuess - [out] the method to guess for (mutually exclusive with classGuess) -// likelihood - [out] an estimate of the likelihood that the guess will succeed +// call - the call +// ilOffset - exact IL offset of the call +// isInterface - whether or not the call target is defined on an interface +// classGuesses - [out] the classes to guess for (mutually exclusive with methodGuess) +// methodGuesses - [out] the methods to guess for (mutually exclusive with classGuess) +// candidatesCount - [out] number of guesses +// likelihoods - [out] estimates of the likelihoods that the guesses will succeed // void Compiler::pickGDV(GenTreeCall* call, IL_OFFSET ilOffset, bool isInterface, - CORINFO_CLASS_HANDLE* classGuess, - CORINFO_METHOD_HANDLE* methodGuess, - unsigned* likelihood) + CORINFO_CLASS_HANDLE* classGuesses, + CORINFO_METHOD_HANDLE* methodGuesses, + int* candidatesCount, + unsigned* likelihoods) { - *classGuess = NO_CLASS_HANDLE; - *methodGuess = NO_METHOD_HANDLE; - *likelihood = 0; + *candidatesCount = 0; - const int maxLikelyClasses = 32; + const int maxLikelyClasses = MAX_GDV_TYPE_CHECKS; LikelyClassMethodRecord likelyClasses[maxLikelyClasses]; unsigned numberOfClasses = 0; if (call->IsVirtualStub() || call->IsVirtualVtable()) @@ -5611,7 +5611,7 @@ void Compiler::pickGDV(GenTreeCall* call, getLikelyClasses(likelyClasses, maxLikelyClasses, fgPgoSchema, fgPgoSchemaCount, fgPgoData, ilOffset); } - const int maxLikelyMethods = 32; + const int maxLikelyMethods = MAX_GDV_TYPE_CHECKS; LikelyClassMethodRecord likelyMethods[maxLikelyMethods]; unsigned numberOfMethods = 0; @@ -5702,16 +5702,26 @@ void Compiler::pickGDV(GenTreeCall* call, unsigned index = static_cast(random->Next(static_cast(numberOfClasses + numberOfMethods))); if (index < numberOfClasses) { - *classGuess = (CORINFO_CLASS_HANDLE)likelyClasses[index].handle; - *likelihood = 100; - JITDUMP("Picked random class for GDV: %p (%s)\n", *classGuess, eeGetClassName(*classGuess)); + classGuesses[0] = (CORINFO_CLASS_HANDLE)likelyClasses[index].handle; + likelihoods[0] = 100; + *candidatesCount = 1; + // TODO: report multiple random candidates. For now we don't do it because with the current impl + // we might give up on all candidates if one of them is not inlinable, so we don't want to reduce + // testing coverage. + // + JITDUMP("Picked random class for GDV: %p (%s)\n", classGuesses[0], eeGetClassName(classGuesses[0])); return; } else { - *methodGuess = (CORINFO_METHOD_HANDLE)likelyMethods[index - numberOfClasses].handle; - *likelihood = 100; - JITDUMP("Picked random method for GDV: %p (%s)\n", *methodGuess, eeGetMethodFullName(*methodGuess)); + methodGuesses[0] = (CORINFO_METHOD_HANDLE)likelyMethods[index - numberOfClasses].handle; + likelihoods[0] = 100; + *candidatesCount = 1; + // TODO: report multiple random candidates. For now we don't do it because with the current impl + // we might give up on all candidates if one of them is not inlinable, so we don't want to reduce + // testing coverage. + // + JITDUMP("Picked random method for GDV: %p (%s)\n", methodGuesses[0], eeGetMethodFullName(methodGuesses[0])); return; } } @@ -5720,25 +5730,68 @@ void Compiler::pickGDV(GenTreeCall* call, // Prefer class guess as it is cheaper if (numberOfClasses > 0) { - unsigned likelihoodThreshold = isInterface ? 25 : 30; - if (likelyClasses[0].likelihood >= likelihoodThreshold) + const int maxNumberOfGuesses = min(MAX_GDV_TYPE_CHECKS, JitConfig.JitGuardedDevirtualizationMaxTypeChecks()); + if (maxNumberOfGuesses == 0) { - *classGuess = (CORINFO_CLASS_HANDLE)likelyClasses[0].handle; - *likelihood = likelyClasses[0].likelihood; + // DOTNET_JitGuardedDevirtualizationMaxTypeChecks=0 means we don't want to do any guarded devirtualization + // Although, we expect users to disable GDV by setting DOTNET_JitEnableGuardedDevirtualization=0 return; } - JITDUMP("Not guessing for class; likelihood is below %s call threshold %u\n", - isInterface ? "interface" : "virtual", likelihoodThreshold); + assert((maxNumberOfGuesses > 0) && (maxNumberOfGuesses <= MAX_GDV_TYPE_CHECKS)); + + unsigned likelihoodThreshold; + if (maxNumberOfGuesses == 1) + { + // We're allowed to make only a single guess - it means we want to work only with dominating types + likelihoodThreshold = isInterface ? 25 : 30; + } + else if (maxNumberOfGuesses == 2) + { + // Two guesses - slightly relax the thresholds + likelihoodThreshold = isInterface ? 15 : 20; + } + else + { + // We're allowed to make more than 2 guesses - pick all types with likelihood >= 10% + likelihoodThreshold = 10; + } + + // We have 'maxNumberOfGuesses' number of classes available + // and we're allowed to make 'maxNumberOfGuesses' number of guesses + // Iterate over the available classes to find classes with likelihoods bigger than + // a specific threshold + // + assert(*candidatesCount == 0); + unsigned totalGuesses = min((unsigned)maxNumberOfGuesses, numberOfClasses); + for (unsigned guessIdx = 0; guessIdx < totalGuesses; guessIdx++) + { + if (likelyClasses[guessIdx].likelihood >= likelihoodThreshold) + { + classGuesses[guessIdx] = (CORINFO_CLASS_HANDLE)likelyClasses[guessIdx].handle; + likelihoods[guessIdx] = likelyClasses[guessIdx].likelihood; + *candidatesCount = *candidatesCount + 1; + JITDUMP("Accepting type %s with likelihood %u as a candidate\n", eeGetClassName(classGuesses[guessIdx]), + likelihoods[guessIdx]) + } + else + { + // The candidates are sorted by likelihood so the rest of the + // guesses will have even lower likelihoods + break; + } + } } if (numberOfMethods > 0) { + // For method guessing we only support a single target for now unsigned likelihoodThreshold = 30; if (likelyMethods[0].likelihood >= likelihoodThreshold) { - *methodGuess = (CORINFO_METHOD_HANDLE)likelyMethods[0].handle; - *likelihood = likelyMethods[0].likelihood; + methodGuesses[0] = (CORINFO_METHOD_HANDLE)likelyMethods[0].handle; + likelihoods[0] = likelyMethods[0].likelihood; + *candidatesCount = 1; return; } @@ -5862,9 +5915,10 @@ void Compiler::considerGuardedDevirtualization(GenTreeCall* call, bool hasPgoData = true; - CORINFO_CLASS_HANDLE likelyClass = NO_CLASS_HANDLE; - CORINFO_METHOD_HANDLE likelyMethod = NO_METHOD_HANDLE; - unsigned likelihood = 0; + CORINFO_CLASS_HANDLE likelyClasses[MAX_GDV_TYPE_CHECKS] = {}; + CORINFO_METHOD_HANDLE likelyMethodes[MAX_GDV_TYPE_CHECKS] = {}; + unsigned likelihoods[MAX_GDV_TYPE_CHECKS] = {}; + int candidatesCount = 0; // We currently only get likely class guesses when there is PGO data // with class profiles. @@ -5875,8 +5929,10 @@ void Compiler::considerGuardedDevirtualization(GenTreeCall* call, } else { - pickGDV(call, ilOffset, isInterface, &likelyClass, &likelyMethod, &likelihood); - if ((likelyClass == NO_CLASS_HANDLE) && (likelyMethod == NO_METHOD_HANDLE)) + pickGDV(call, ilOffset, isInterface, likelyClasses, likelyMethodes, &candidatesCount, likelihoods); + assert((unsigned)candidatesCount <= MAX_GDV_TYPE_CHECKS); + assert((unsigned)candidatesCount <= (unsigned)JitConfig.JitGuardedDevirtualizationMaxTypeChecks()); + if (candidatesCount == 0) { hasPgoData = false; } @@ -5933,7 +5989,9 @@ void Compiler::considerGuardedDevirtualization(GenTreeCall* call, if (!info.compCompHnd->resolveVirtualMethod(&dvInfo)) { JITDUMP("Can't figure out which method would be invoked, sorry\n"); - return; + // Maybe other candidates will be resolved. + // Although, we no longer can remove the fallback (we never do it currently anyway) + break; } CORINFO_METHOD_HANDLE exactMethod = dvInfo.devirtualizedMethod; @@ -5964,103 +6022,119 @@ void Compiler::considerGuardedDevirtualization(GenTreeCall* call, return; } - uint32_t likelyClassAttribs = 0; - if (likelyClass != NO_CLASS_HANDLE) + // Iterate over the guesses + for (int candidateId = 0; candidateId < candidatesCount; candidateId++) { - likelyClassAttribs = info.compCompHnd->getClassAttribs(likelyClass); + CORINFO_CLASS_HANDLE likelyClass = likelyClasses[candidateId]; + CORINFO_METHOD_HANDLE likelyMethod = likelyMethodes[candidateId]; + unsigned likelihood = likelihoods[candidateId]; - if ((likelyClassAttribs & CORINFO_FLG_ABSTRACT) != 0) + uint32_t likelyClassAttribs = 0; + if (likelyClass != NO_CLASS_HANDLE) { - // We may see an abstract likely class, if we have a stale profile. - // No point guessing for this. - // - JITDUMP("Not guessing for class; abstract (stale profile)\n"); - return; - } + likelyClassAttribs = info.compCompHnd->getClassAttribs(likelyClass); - // Figure out which method will be called. - // - CORINFO_DEVIRTUALIZATION_INFO dvInfo; - dvInfo.virtualMethod = baseMethod; - dvInfo.objClass = likelyClass; - dvInfo.context = *pContextHandle; - dvInfo.exactContext = *pContextHandle; - dvInfo.pResolvedTokenVirtualMethod = nullptr; + if ((likelyClassAttribs & CORINFO_FLG_ABSTRACT) != 0) + { + // We may see an abstract likely class, if we have a stale profile. + // No point guessing for this. + // + JITDUMP("Not guessing for class; abstract (stale profile)\n"); - const bool canResolve = info.compCompHnd->resolveVirtualMethod(&dvInfo); + // Continue checking other candidates, maybe some of them aren't stale. + break; + } - if (!canResolve) - { - JITDUMP("Can't figure out which method would be invoked, sorry\n"); - return; - } + // Figure out which method will be called. + // + CORINFO_DEVIRTUALIZATION_INFO dvInfo; + dvInfo.virtualMethod = baseMethod; + dvInfo.objClass = likelyClass; + dvInfo.context = *pContextHandle; + dvInfo.exactContext = *pContextHandle; + dvInfo.pResolvedTokenVirtualMethod = nullptr; - likelyMethod = dvInfo.devirtualizedMethod; - } + const bool canResolve = info.compCompHnd->resolveVirtualMethod(&dvInfo); - uint32_t likelyMethodAttribs = info.compCompHnd->getMethodAttribs(likelyMethod); + if (!canResolve) + { + JITDUMP("Can't figure out which method would be invoked, sorry\n"); - if (likelyClass == NO_CLASS_HANDLE) - { - // For method GDV do a few more checks that we get for free in the - // resolve call above for class-based GDV. - if ((likelyMethodAttribs & CORINFO_FLG_STATIC) != 0) - { - assert((fgPgoSource != ICorJitInfo::PgoSource::Dynamic) || call->IsDelegateInvoke()); - JITDUMP("Cannot currently handle devirtualizing static delegate calls, sorry\n"); - return; + // Continue checking other candidates, maybe some of them will succeed. + break; + } + + likelyMethod = dvInfo.devirtualizedMethod; } - CORINFO_CLASS_HANDLE definingClass = info.compCompHnd->getMethodClass(likelyMethod); - likelyClassAttribs = info.compCompHnd->getClassAttribs(definingClass); + uint32_t likelyMethodAttribs = info.compCompHnd->getMethodAttribs(likelyMethod); - // For instance methods on value classes we need an extended check to - // check for the unboxing stub. This is NYI. - // Note: For dynamic PGO likelyMethod above will be the unboxing stub - // which would fail GDV for other reasons. - // However, with static profiles or textual PGO input it is still - // possible that likelyMethod is not the unboxing stub. So we do need - // this explicit check. - if ((likelyClassAttribs & CORINFO_FLG_VALUECLASS) != 0) + if (likelyClass == NO_CLASS_HANDLE) { - JITDUMP("Cannot currently handle devirtualizing delegate calls on value types, sorry\n"); - return; - } + // We don't support multiple candidates for method guessing yet. + assert(candidateId == 0); - // Verify that the call target and args look reasonable so that the JIT - // does not blow up during inlining/call morphing. - // - // NOTE: Once we want to support devirtualization of delegate calls to - // static methods and remove the check above we will start failing here - // for delegates pointing to static methods that have the first arg - // bound. For example: - // - // public static void E(this C c) ... - // Action a = new C().E; - // - // The delegate instance looks exactly like one pointing to an instance - // method in this case and the call will have zero args while the - // signature has 1 arg. - // - if (!isCompatibleMethodGDV(call, likelyMethod)) - { - JITDUMP("Target for method-based GDV is incompatible (stale profile?)\n"); - assert((fgPgoSource != ICorJitInfo::PgoSource::Dynamic) && "Unexpected stale profile in dynamic PGO data"); - return; + // For method GDV do a few more checks that we get for free in the + // resolve call above for class-based GDV. + if ((likelyMethodAttribs & CORINFO_FLG_STATIC) != 0) + { + assert((fgPgoSource != ICorJitInfo::PgoSource::Dynamic) || call->IsDelegateInvoke()); + JITDUMP("Cannot currently handle devirtualizing static delegate calls, sorry\n"); + break; + } + + CORINFO_CLASS_HANDLE definingClass = info.compCompHnd->getMethodClass(likelyMethod); + likelyClassAttribs = info.compCompHnd->getClassAttribs(definingClass); + + // For instance methods on value classes we need an extended check to + // check for the unboxing stub. This is NYI. + // Note: For dynamic PGO likelyMethod above will be the unboxing stub + // which would fail GDV for other reasons. + // However, with static profiles or textual PGO input it is still + // possible that likelyMethod is not the unboxing stub. So we do need + // this explicit check. + if ((likelyClassAttribs & CORINFO_FLG_VALUECLASS) != 0) + { + JITDUMP("Cannot currently handle devirtualizing delegate calls on value types, sorry\n"); + break; + } + + // Verify that the call target and args look reasonable so that the JIT + // does not blow up during inlining/call morphing. + // + // NOTE: Once we want to support devirtualization of delegate calls to + // static methods and remove the check above we will start failing here + // for delegates pointing to static methods that have the first arg + // bound. For example: + // + // public static void E(this C c) ... + // Action a = new C().E; + // + // The delegate instance looks exactly like one pointing to an instance + // method in this case and the call will have zero args while the + // signature has 1 arg. + // + if (!isCompatibleMethodGDV(call, likelyMethod)) + { + JITDUMP("Target for method-based GDV is incompatible (stale profile?)\n"); + assert((fgPgoSource != ICorJitInfo::PgoSource::Dynamic) && + "Unexpected stale profile in dynamic PGO data"); + break; + } } - } #ifdef DEBUG - char buffer[256]; - JITDUMP("%s call would invoke method %s\n", - isInterface ? "interface" : call->IsDelegateInvoke() ? "delegate" : "virtual", - eeGetMethodFullName(likelyMethod, true, true, buffer, sizeof(buffer))); + char buffer[256]; + JITDUMP("%s call would invoke method %s\n", + isInterface ? "interface" : call->IsDelegateInvoke() ? "delegate" : "virtual", + eeGetMethodFullName(likelyMethod, true, true, buffer, sizeof(buffer))); #endif - // Add this as a potential candidate. - // - addGuardedDevirtualizationCandidate(call, likelyMethod, likelyClass, likelyMethodAttribs, likelyClassAttribs, - likelihood); + // Add this as a potential candidate. + // + addGuardedDevirtualizationCandidate(call, likelyMethod, likelyClass, likelyMethodAttribs, likelyClassAttribs, + likelihood); + } } //------------------------------------------------------------------------ @@ -6204,6 +6278,18 @@ void Compiler::impMarkInlineCandidate(GenTree* callNode, CORINFO_CALL_INFO* callInfo, IL_OFFSET ilOffset) { + if (!opts.OptEnabled(CLFLG_INLINING)) + { + /* XXX Mon 8/18/2008 + * This assert is misleading. The caller does not ensure that we have CLFLG_INLINING set before + * calling impMarkInlineCandidate. However, if this assert trips it means that we're an inlinee and + * CLFLG_MINOPT is set. That doesn't make a lot of sense. If you hit this assert, work back and + * figure out why we did not set MAXOPT for this compile. + */ + assert(!compIsForInlining()); + return; + } + GenTreeCall* call = callNode->AsCall(); // Call might not have an inline candidate info yet (will be set by impMarkInlineCandidateHelper) @@ -6257,7 +6343,7 @@ void Compiler::impMarkInlineCandidate(GenTree* callNode, JITDUMP("Revoking guarded devirtualization candidacy for call [%06u]: target method can't be inlined\n", dspTreeID(call)); - call->ClearGuardedDevirtualizationCandidate(); + call->ClearInlineInfo(); } //------------------------------------------------------------------------ @@ -6293,17 +6379,7 @@ void Compiler::impMarkInlineCandidateHelper(GenTreeCall* call, // Let the strategy know there's another call impInlineRoot()->m_inlineStrategy->NoteCall(); - if (!opts.OptEnabled(CLFLG_INLINING)) - { - /* XXX Mon 8/18/2008 - * This assert is misleading. The caller does not ensure that we have CLFLG_INLINING set before - * calling impMarkInlineCandidate. However, if this assert trips it means that we're an inlinee and - * CLFLG_MINOPT is set. That doesn't make a lot of sense. If you hit this assert, work back and - * figure out why we did not set MAXOPT for this compile. - */ - assert(!compIsForInlining()); - return; - } + assert(opts.OptEnabled(CLFLG_INLINING)); // Don't inline if not optimizing root method if (opts.compDbgCode) diff --git a/src/coreclr/jit/indirectcalltransformer.cpp b/src/coreclr/jit/indirectcalltransformer.cpp index 15042ce6d744e3..bb2f316bb327d6 100644 --- a/src/coreclr/jit/indirectcalltransformer.cpp +++ b/src/coreclr/jit/indirectcalltransformer.cpp @@ -534,12 +534,9 @@ class IndirectCallTransformer return call; } - //------------------------------------------------------------------------ - // ClearFlag: clear guarded devirtualization candidate flag from the original call. - // virtual void ClearFlag() { - origCall->ClearGuardedDevirtualizationCandidate(); + // We remove the GDV flag from the call in the CreateElse } virtual UINT8 GetChecksCount() @@ -587,9 +584,18 @@ class IndirectCallTransformer prevCheckBlock->bbJumpDest = checkBlock; compiler->fgAddRefPred(checkBlock, prevCheckBlock); - // Weight for the new secondary check is the difference between the previous check and the thenBlock. - checkBlock->inheritWeightPercentage(prevCheckBlock, - 100 - origCall->GetGDVCandidateInfo(checkIdx)->likelihood); + // Calculate the total likelihood for this check as a sum of likelihoods + // of all previous candidates (thenBlocks) + unsigned checkLikelihood = 100; + for (uint8_t previousCandidate = 0; previousCandidate < checkIdx; previousCandidate++) + { + checkLikelihood -= origCall->GetGDVCandidateInfo(previousCandidate)->likelihood; + } + + // Make sure we didn't overflow + assert(checkLikelihood <= 100); + + checkBlock->inheritWeightPercentage(currBlock, checkLikelihood); } // Find last arg with a side effect. All args with any effect @@ -839,6 +845,7 @@ class IndirectCallTransformer // special candidate helper and we need to use the new 'this'. GenTreeCall* call = compiler->gtCloneCandidateCall(origCall); call->gtArgs.GetThisArg()->SetEarlyNode(compiler->gtNewLclvNode(thisTemp, TYP_REF)); + call->SetIsGuarded(); JITDUMP("Direct call [%06u] in block " FMT_BB "\n", compiler->dspTreeID(call), block->bbNum); @@ -994,12 +1001,16 @@ class IndirectCallTransformer // Make sure it didn't overflow assert(elseLikelihood <= 100); + // Remove everything related to inlining from the original call + origCall->ClearInlineInfo(); + elseBlock->inheritWeightPercentage(currBlock, elseLikelihood); GenTreeCall* call = origCall; Statement* newStmt = compiler->gtNewStmt(call, stmt->GetDebugInfo()); call->gtFlags &= ~GTF_CALL_INLINE_CANDIDATE; + call->SetIsGuarded(); JITDUMP("Residual call [%06u] moved to block " FMT_BB "\n", compiler->dspTreeID(call), elseBlock->bbNum); diff --git a/src/coreclr/jit/instr.cpp b/src/coreclr/jit/instr.cpp index b942ddd6d878d9..93c4e601bb7811 100644 --- a/src/coreclr/jit/instr.cpp +++ b/src/coreclr/jit/instr.cpp @@ -335,6 +335,22 @@ bool CodeGenInterface::instIsFP(instruction ins) #endif } +#if defined(TARGET_XARCH) +/***************************************************************************** + * + * Returns non-zero if the given CPU instruction is an embedded broadcast + * compatible instruction. + */ + +// static inline +bool CodeGenInterface::instIsEmbeddedBroadcastCompatible(instruction ins) +{ + assert((unsigned)ins < ArrLen(instInfo)); + + return (instInfo[ins] & INS_Flags_EmbeddedBroadcastSupported) != 0; +} +#endif // TARGET_XARCH + /***************************************************************************** * * Generate a set instruction. @@ -749,7 +765,7 @@ void CodeGen::inst_RV_SH( // logic for determining what "kind" of operand "op" is. // // Arguments: -// op - The operand node for which to obtain the descriptor +// op - The operand node for which to obtain the descriptor. // // Return Value: // The operand descriptor for "op". @@ -795,11 +811,69 @@ CodeGen::OperandDesc CodeGen::genOperandDesc(GenTree* op) assert(op->OperIsHWIntrinsic()); #if defined(FEATURE_HW_INTRINSICS) - GenTreeHWIntrinsic* hwintrinsic = op->AsHWIntrinsic(); - NamedIntrinsic intrinsicId = hwintrinsic->GetHWIntrinsicId(); - + GenTreeHWIntrinsic* hwintrinsic = op->AsHWIntrinsic(); + NamedIntrinsic intrinsicId = hwintrinsic->GetHWIntrinsicId(); + var_types simdBaseType = hwintrinsic->GetSimdBaseType(); switch (intrinsicId) { + case NI_AVX_BroadcastScalarToVector128: + case NI_AVX_BroadcastScalarToVector256: + { + // we have the assumption that AVX_BroadcastScalarToVector* + // only take the memory address as the operand. + assert(hwintrinsic->isContained()); + assert(hwintrinsic->OperIsMemoryLoad()); + assert(hwintrinsic->GetOperandCount() == 1); + assert(varTypeIsFloating(simdBaseType)); + GenTree* hwintrinsicChild = hwintrinsic->Op(1); + assert(hwintrinsicChild->isContained()); + if (hwintrinsicChild->OperIs(GT_LCL_ADDR, GT_CLS_VAR_ADDR, GT_CNS_INT, GT_LEA)) + { + addr = hwintrinsic->Op(1); + break; + } + else + { + assert(hwintrinsicChild->OperIs(GT_LCL_VAR)); + return OperandDesc(simdBaseType, hwintrinsicChild); + } + } + + case NI_SSE3_MoveAndDuplicate: + case NI_AVX2_BroadcastScalarToVector128: + case NI_AVX2_BroadcastScalarToVector256: + case NI_AVX512F_BroadcastScalarToVector512: + { + assert(hwintrinsic->isContained()); + if (intrinsicId == NI_SSE3_MoveAndDuplicate) + { + assert(simdBaseType == TYP_DOUBLE); + } + // If broadcast node is contained, should mean that we have some forms like + // Broadcast -> CreateScalarUnsafe -> Scalar. + // If so, directly emit scalar. + // In the codes below, we specially handle the `Broadcast -> CNS_INT` form and + // handle other cases recursively. + GenTree* hwintrinsicChild = hwintrinsic->Op(1); + assert(hwintrinsicChild->isContained()); + if (hwintrinsicChild->OperIs(GT_CNS_INT)) + { + // a special case is when the operand of CreateScalarUnsafe is in integer type, + // CreateScalarUnsafe node will be fold, so we directly match a pattern of + // broadcast -> LCL_VAR(TYP_(U)INT) + ssize_t scalarValue = hwintrinsicChild->AsIntCon()->IconValue(); + UNATIVE_OFFSET cnum = emit->emitDataConst(&scalarValue, genTypeSize(simdBaseType), + genTypeSize(simdBaseType), simdBaseType); + return OperandDesc(compiler->eeFindJitDataOffs(cnum)); + } + else + { + // If the operand of broadcast is not a constant integer, + // we handle all the other cases recursively. + return genOperandDesc(hwintrinsicChild); + } + break; + } case NI_Vector128_CreateScalarUnsafe: case NI_Vector256_CreateScalarUnsafe: case NI_Vector512_CreateScalarUnsafe: @@ -865,8 +939,10 @@ CodeGen::OperandDesc CodeGen::genOperandDesc(GenTree* op) return OperandDesc(emit->emitFltOrDblConst(op->AsDblCon()->DconValue(), emitTypeSize(op))); case GT_CNS_INT: + { assert(op->isContainedIntOrIImmed()); return OperandDesc(op->AsIntCon()->IconValue(), op->AsIntCon()->ImmedValNeedsReloc(compiler)); + } case GT_CNS_VEC: { @@ -1096,19 +1172,49 @@ void CodeGen::inst_RV_TT_IV(instruction ins, emitAttr attr, regNumber reg1, GenT } } +//------------------------------------------------------------------------ +// IsEmbeddedBroadcastEnabled: determine if embedded broadcast can be enabled +// +// Arguments: +// ins -- The instruction being emitted +// op -- The second operand of the instruction. +// +#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS) +bool CodeGenInterface::IsEmbeddedBroadcastEnabled(instruction ins, GenTree* op) +{ + // To enable embedded broadcast, we need 3 things, + // 1. EVEX enabled. + // 2. Embedded broadcast compatible intrinsics + // 3. A contained broadcast scalar node + if (!GetEmitter()->UseEvexEncoding()) + { + return false; + } + if (!instIsEmbeddedBroadcastCompatible(ins)) + { + return false; + } + if (!op->isContained() || !op->OperIsHWIntrinsic()) + { + return false; + } + + return op->AsHWIntrinsic()->OperIsBroadcastScalar(); +} +#endif // TARGET_XARCH && FEATURE_HW_INTRINSICS + //------------------------------------------------------------------------ // inst_RV_RV_TT: Generates an instruction that takes 2 operands: // a register operand and an operand that may be in memory or register // 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 -// 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 +// isRMW -- true if the instruction is RMW; otherwise, false void CodeGen::inst_RV_RV_TT( instruction ins, emitAttr size, regNumber targetReg, regNumber op1Reg, GenTree* op2, bool isRMW) { @@ -1118,15 +1224,25 @@ void CodeGen::inst_RV_RV_TT( // TODO-XArch-CQ: Commutative operations can have op1 be contained // TODO-XArch-CQ: Non-VEX encoded instructions can have both ops contained + insOpts instOptions = INS_OPTS_NONE; +#if defined(TARGET_XARCH) && defined(FEATURE_HW_INTRINSICS) + bool IsEmbBroadcast = CodeGenInterface::IsEmbeddedBroadcastEnabled(ins, op2); + if (IsEmbBroadcast) + { + instOptions = INS_OPTS_EVEX_b; + } +#endif // TARGET_XARCH && FEATURE_HW_INTRINSICS OperandDesc op2Desc = genOperandDesc(op2); switch (op2Desc.GetKind()) { case OperandKind::ClsVar: - emit->emitIns_SIMD_R_R_C(ins, size, targetReg, op1Reg, op2Desc.GetFieldHnd(), 0); + { + emit->emitIns_SIMD_R_R_C(ins, size, targetReg, op1Reg, op2Desc.GetFieldHnd(), 0, instOptions); break; - + } case OperandKind::Local: - emit->emitIns_SIMD_R_R_S(ins, size, targetReg, op1Reg, op2Desc.GetVarNum(), op2Desc.GetLclOffset()); + emit->emitIns_SIMD_R_R_S(ins, size, targetReg, op1Reg, op2Desc.GetVarNum(), op2Desc.GetLclOffset(), + instOptions); break; case OperandKind::Indir: @@ -1135,7 +1251,7 @@ void CodeGen::inst_RV_RV_TT( // temporary GT_IND to generate code with. GenTreeIndir indirForm; GenTreeIndir* indir = op2Desc.GetIndirForm(&indirForm); - emit->emitIns_SIMD_R_R_A(ins, size, targetReg, op1Reg, indir); + emit->emitIns_SIMD_R_R_A(ins, size, targetReg, op1Reg, indir, instOptions); } break; diff --git a/src/coreclr/jit/instr.h b/src/coreclr/jit/instr.h index df8658195f8da9..bbc8089376ae58 100644 --- a/src/coreclr/jit/instr.h +++ b/src/coreclr/jit/instr.h @@ -146,8 +146,7 @@ enum insFlags : uint64_t // Avx INS_Flags_IsDstDstSrcAVXInstruction = 1ULL << 26, INS_Flags_IsDstSrcSrcAVXInstruction = 1ULL << 27, - INS_Flags_IsMskSrcSrcEvexInstruction = 1ULL << 28, - INS_Flags_Is3OperandInstructionMask = (INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_IsDstSrcSrcAVXInstruction | INS_Flags_IsMskSrcSrcEvexInstruction), + INS_Flags_Is3OperandInstructionMask = (INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_IsDstSrcSrcAVXInstruction), // w and s bits INS_FLAGS_Has_Wbit = 1ULL << 29, @@ -180,10 +179,20 @@ enum insFlags : uint64_t KInstruction = 1ULL << 41, + // EVEX feature: embedded broadcast + INS_Flags_EmbeddedBroadcastSupported = 1ULL << 42, + // TODO-Cleanup: Remove this flag and its usage from TARGET_XARCH INS_FLAGS_DONT_CARE = 0x00ULL, }; +enum insOpts: unsigned +{ + INS_OPTS_NONE, + + INS_OPTS_EVEX_b +}; + #elif defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) // TODO-Cleanup: Move 'insFlags' under TARGET_ARM enum insFlags: unsigned @@ -350,7 +359,7 @@ enum insOpts : unsigned INS_OPTS_JALR, // see ::emitIns_J_R(). INS_OPTS_J, // see ::emitIns_J(). INS_OPTS_J_cond, // see ::emitIns_J_cond_la(). - INS_OPTS_I, // see ::emitIns_I_la(). + INS_OPTS_I, // see ::emitLoadImmediate(). INS_OPTS_C, // see ::emitIns_Call(). INS_OPTS_RELOC, // see ::emitIns_R_AI(). }; diff --git a/src/coreclr/jit/instrsxarch.h b/src/coreclr/jit/instrsxarch.h index 0bb638bfea69bd..161df4485e0d98 100644 --- a/src/coreclr/jit/instrsxarch.h +++ b/src/coreclr/jit/instrsxarch.h @@ -191,7 +191,7 @@ INSTMUL(imul_15, "imul", IUM_RD, BAD_CODE, 0x4400003868, INST3(FIRST_SSE_INSTRUCTION, "FIRST_SSE_INSTRUCTION", IUM_WR, BAD_CODE, BAD_CODE, BAD_CODE, INS_TT_NONE, INS_FLAGS_None) // SSE -INST3(addps, "addps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x58), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Add packed singles +INST3(addps, "addps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x58), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Add packed singles INST3(addss, "addss", IUM_WR, BAD_CODE, BAD_CODE, SSEFLT(0x58), INS_TT_TUPLE1_SCALAR, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Add scalar singles INST3(andnps, "andnps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x55), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // And-Not packed singles INST3(andps, "andps", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x54), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // AND packed singles @@ -240,7 +240,7 @@ INST3(unpcklps, "unpcklps", IUM_WR, BAD_CODE, BAD_CODE, 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) // XOR packed singles // SSE2 -INST3(addpd, "addpd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x58), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Add packed doubles +INST3(addpd, "addpd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x58), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Add packed doubles INST3(addsd, "addsd", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x58), INS_TT_TUPLE1_SCALAR, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Add scalar doubles INST3(andnpd, "andnpd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x55), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // And-Not packed doubles INST3(andpd, "andpd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x54), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // AND packed doubles @@ -290,8 +290,8 @@ INST3(packssdw, "packssdw", IUM_WR, BAD_CODE, BAD_CODE, 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 -INST3(paddd, "paddd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xFE), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Add packed double-word (32-bit) integers -INST3(paddq, "paddq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xD4), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Add packed quad-word (64-bit) integers +INST3(paddd, "paddd", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xFE), INS_TT_FULL, Input_32Bit | REX_W0_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Add packed double-word (32-bit) integers +INST3(paddq, "paddq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xD4), INS_TT_FULL, Input_64Bit | REX_W1_EVEX | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction | INS_Flags_EmbeddedBroadcastSupported) // Add packed quad-word (64-bit) integers INST3(paddsb, "paddsb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xEC), INS_TT_FULL_MEM, Input_8Bit | REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Add packed signed byte integers and saturate the results INST3(paddsw, "paddsw", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xED), INS_TT_FULL_MEM, Input_16Bit | REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Add packed signed word integers and saturate the results INST3(paddusb, "paddusb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xDC), INS_TT_FULL_MEM, Input_8Bit | REX_WIG | Encoding_VEX | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Add packed unsigned byte integers and saturate the results @@ -608,19 +608,28 @@ 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(kmovw_gpr, "kmovw", IUM_WR, BAD_CODE, BAD_CODE, PCKFLT(0x92), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) -INST3(kmovw_msk, "kmovw", IUM_WR, PCKFLT(0x91), BAD_CODE, PCKFLT(0x90), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) -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) +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(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_IsMskSrcSrcEvexInstruction) // 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_IsMskSrcSrcEvexInstruction) // 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_IsMskSrcSrcEvexInstruction) // 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_IsMskSrcSrcEvexInstruction) // compare scalar doubles +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(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 @@ -658,10 +667,10 @@ INST3(vpandq, "pandq", IUM_WR, BAD_CODE, BAD_ INST3(vpandnq, "pandnq", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0xDF), INS_TT_FULL, Input_64Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // 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_IsMskSrcSrcEvexInstruction) // 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_IsMskSrcSrcEvexInstruction) // 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_IsMskSrcSrcEvexInstruction) // 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_IsMskSrcSrcEvexInstruction) // Packed compare 64-bit integers for equality +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 @@ -735,25 +744,47 @@ INST3(vshufi32x4, "shufi32x4", IUM_WR, BAD_CODE, BAD_ 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 // AVX512BW -INST3(kmovd_gpr, "kmovd", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x92), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) -INST3(kmovd_msk, "kmovd", IUM_WR, PCKDBL(0x91), BAD_CODE, PCKDBL(0x90), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) -INST3(kmovq_gpr, "kmovq", IUM_WR, BAD_CODE, BAD_CODE, SSEDBL(0x92), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) -INST3(kmovq_msk, "kmovq", IUM_WR, PCKFLT(0x91), BAD_CODE, PCKFLT(0x90), INS_TT_NONE, REX_W1 | Encoding_VEX | KInstruction) -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) -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) +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(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) INST3(vmovdqu16, "movdqu16", IUM_WR, SSEFLT(0x7F), BAD_CODE, SSEFLT(0x6F), INS_TT_FULL_MEM, Input_16Bit | REX_W1 | Encoding_EVEX) INST3(vpbroadcastb_gpr, "pbroadcastb", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x7A), INS_TT_TUPLE1_SCALAR, Input_8Bit | REX_W0 | Encoding_EVEX) // Broadcast int8 value from gpr to entire register INST3(vpbroadcastw_gpr, "pbroadcastw", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x7B), INS_TT_TUPLE1_SCALAR, Input_16Bit | REX_W0 | Encoding_EVEX) // Broadcast int16 value from gpr to entire register -INST3(vpcmpb, "pcmpb", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x3F), INS_TT_FULL_MEM, Input_8Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsMskSrcSrcEvexInstruction) -INST3(vpcmpeqb, "pcmpeqb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x74), INS_TT_FULL_MEM, Input_8Bit | REX_WIG | Encoding_EVEX | INS_Flags_IsMskSrcSrcEvexInstruction) // Packed compare 8-bit integers for equality -INST3(vpcmpeqw, "pcmpeqw", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x75), INS_TT_FULL_MEM, Input_16Bit | REX_WIG | Encoding_EVEX | INS_Flags_IsMskSrcSrcEvexInstruction) // Packed compare 16-bit integers for equality -INST3(vpcmpgtb, "pcmpgtb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x64), INS_TT_FULL_MEM, Input_8Bit | REX_WIG | Encoding_EVEX | INS_Flags_IsMskSrcSrcEvexInstruction) // Packed compare 8-bit signed integers for greater than -INST3(vpcmpgtw, "pcmpgtw", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x65), INS_TT_FULL_MEM, Input_16Bit | REX_WIG | Encoding_EVEX | INS_Flags_IsMskSrcSrcEvexInstruction) // Packed compare 16-bit signed integers for greater than -INST3(vpcmpw, "pcmpw", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x3F), INS_TT_FULL_MEM, Input_16Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsMskSrcSrcEvexInstruction) -INST3(vpcmpub, "pcmpub", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x3E), INS_TT_FULL_MEM, Input_8Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsMskSrcSrcEvexInstruction) -INST3(vpcmpuw, "pcmpuw", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x3E), INS_TT_FULL_MEM, Input_16Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsMskSrcSrcEvexInstruction) +INST3(vpcmpb, "pcmpb", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x3F), INS_TT_FULL_MEM, Input_8Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) +INST3(vpcmpeqb, "pcmpeqb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x74), INS_TT_FULL_MEM, Input_8Bit | REX_WIG | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed compare 8-bit integers for equality +INST3(vpcmpeqw, "pcmpeqw", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x75), INS_TT_FULL_MEM, Input_16Bit | REX_WIG | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed compare 16-bit integers for equality +INST3(vpcmpgtb, "pcmpgtb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x64), INS_TT_FULL_MEM, Input_8Bit | REX_WIG | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed compare 8-bit signed integers for greater than +INST3(vpcmpgtw, "pcmpgtw", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x65), INS_TT_FULL_MEM, Input_16Bit | REX_WIG | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) // Packed compare 16-bit signed integers for greater than +INST3(vpcmpw, "pcmpw", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x3F), INS_TT_FULL_MEM, Input_16Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) +INST3(vpcmpub, "pcmpub", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x3E), INS_TT_FULL_MEM, Input_8Bit | REX_W0 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) +INST3(vpcmpuw, "pcmpuw", IUM_WR, BAD_CODE, BAD_CODE, SSE3A(0x3E), INS_TT_FULL_MEM, Input_16Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstDstSrcAVXInstruction) INST3(vpermw, "permw", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x8D), INS_TT_FULL_MEM, Input_16Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Permute Packed Doublewords Elements INST3(vpermi2w, "permi2w", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x75), INS_TT_FULL_MEM, Input_16Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Full Permute From Two Tables Overwriting the Index INST3(vpermt2w, "permt2w", IUM_WR, BAD_CODE, BAD_CODE, SSE38(0x7D), INS_TT_FULL_MEM, Input_16Bit | REX_W1 | Encoding_EVEX | INS_Flags_IsDstSrcSrcAVXInstruction) // Full Permute From Two Tables Overwriting one Table @@ -775,9 +806,21 @@ INST3(vplzcntd, "plzcntd", IUM_WR, BAD_CODE, BAD_ 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 // AVX512DQ -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) -INST3(kmovb_gpr, "kmovb", IUM_WR, BAD_CODE, BAD_CODE, PCKDBL(0x92), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) -INST3(kmovb_msk, "kmovb", IUM_WR, PCKDBL(0x91), BAD_CODE, PCKDBL(0x90), INS_TT_NONE, REX_W0 | Encoding_VEX | KInstruction) +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 diff --git a/src/coreclr/jit/jitconfigvalues.h b/src/coreclr/jit/jitconfigvalues.h index 6ab73d6abde378..8657940e5a00c5 100644 --- a/src/coreclr/jit/jitconfigvalues.h +++ b/src/coreclr/jit/jitconfigvalues.h @@ -528,7 +528,7 @@ CONFIG_INTEGER(JitEnableGuardedDevirtualization, W("JitEnableGuardedDevirtualiza #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 ^ -CONFIG_INTEGER(JitGuardedDevirtualizationMaxTypeChecks, W("JitGuardedDevirtualizationMaxTypeChecks"), 3) +CONFIG_INTEGER(JitGuardedDevirtualizationMaxTypeChecks, W("JitGuardedDevirtualizationMaxTypeChecks"), 1) // Various policies for GuardedDevirtualization CONFIG_INTEGER(JitGuardedDevirtualizationChainLikelihood, W("JitGuardedDevirtualizationChainLikelihood"), 0x4B) // 75 @@ -539,11 +539,11 @@ CONFIG_INTEGER(JitRandomGuardedDevirtualization, W("JitRandomGuardedDevirtualiza #endif // DEBUG // Enable insertion of patchpoints into Tier0 methods, switching to optimized where needed. -#if defined(TARGET_AMD64) || defined(TARGET_ARM64) +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) CONFIG_INTEGER(TC_OnStackReplacement, W("TC_OnStackReplacement"), 1) #else CONFIG_INTEGER(TC_OnStackReplacement, W("TC_OnStackReplacement"), 0) -#endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) +#endif // defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) // Initial patchpoint counter value used by jitted code CONFIG_INTEGER(TC_OnStackReplacement_InitialCounter, W("TC_OnStackReplacement_InitialCounter"), 1000) // Enable partial compilation for Tier0 methods diff --git a/src/coreclr/jit/jitee.h b/src/coreclr/jit/jitee.h index 7c3089833bc332..ac51df952ab420 100644 --- a/src/coreclr/jit/jitee.h +++ b/src/coreclr/jit/jitee.h @@ -60,7 +60,7 @@ class JitFlags JIT_FLAG_BBINSTR_IF_LOOPS = 32, // JIT must instrument current method if it has loops JIT_FLAG_PUBLISH_SECRET_PARAM = 33, // JIT must place stub secret param into local 0. (used by IL stubs) JIT_FLAG_UNUSED13 = 34, - JIT_FLAG_SAMPLING_JIT_BACKGROUND = 35, // JIT is being invoked as a result of stack sampling for hot methods in the background + JIT_FLAG_UNUSED14 = 35, JIT_FLAG_USE_PINVOKE_HELPERS = 36, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions JIT_FLAG_REVERSE_PINVOKE = 37, // The JIT should insert REVERSE_PINVOKE_{ENTER,EXIT} helpers into method prolog/epilog JIT_FLAG_TRACK_TRANSITIONS = 38, // The JIT should insert the helper variants that track transitions. @@ -192,7 +192,6 @@ class JitFlags FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_BBOPT, JIT_FLAG_BBOPT); FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_FRAMED, JIT_FLAG_FRAMED); FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_PUBLISH_SECRET_PARAM, JIT_FLAG_PUBLISH_SECRET_PARAM); - FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_SAMPLING_JIT_BACKGROUND, JIT_FLAG_SAMPLING_JIT_BACKGROUND); FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_USE_PINVOKE_HELPERS, JIT_FLAG_USE_PINVOKE_HELPERS); FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_REVERSE_PINVOKE, JIT_FLAG_REVERSE_PINVOKE); FLAGS_EQUAL(CORJIT_FLAGS::CORJIT_FLAG_TIER0, JIT_FLAG_TIER0); diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 454d65172543bc..80d9493daca427 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -1757,7 +1757,8 @@ bool Compiler::StructPromotionHelper::CanPromoteStructType(CORINFO_CLASS_HANDLE #if defined(FEATURE_SIMD) // getMaxVectorByteLength() represents the size of the largest primitive type that we can struct promote. - const unsigned maxSize = MAX_NumOfFieldsInPromotableStruct * compiler->getMaxVectorByteLength(); + const unsigned maxSize = + MAX_NumOfFieldsInPromotableStruct * max(compiler->getMaxVectorByteLength(), sizeof(double)); #else // !FEATURE_SIMD // sizeof(double) represents the size of the largest primitive type that we can struct promote. const unsigned maxSize = MAX_NumOfFieldsInPromotableStruct * sizeof(double); @@ -5286,7 +5287,7 @@ void Compiler::lvaFixVirtualFrameOffsets() if (opts.IsOSR()) { -#if defined(TARGET_AMD64) || defined(TARGET_ARM64) +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) // Stack offset includes Tier0 frame. // JITDUMP("--- delta bump %d for OSR + Tier0 frame\n", info.compPatchpointInfo->TotalFrameSize()); @@ -5391,7 +5392,7 @@ void Compiler::lvaFixVirtualFrameOffsets() #endif // FEATURE_FIXED_OUT_ARGS -#if defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) +#if defined(TARGET_ARM64) || 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 @@ -5403,7 +5404,14 @@ void Compiler::lvaFixVirtualFrameOffsets() { lvaTable[lvaRetAddrVar].SetStackOffset(REGSIZE_BYTES); } -#endif // TARGET_ARM64 || TARGET_LOONGARCH64 || TARGET_RISCV64 +#elif defined(TARGET_LOONGARCH64) + assert(codeGen->isFramePointerUsed()); + if (lvaRetAddrVar != BAD_VAR_NUM) + { + // For LoongArch64, the RA is below the fp. see the `genPushCalleeSavedRegisters` + lvaTable[lvaRetAddrVar].SetStackOffset(-REGSIZE_BYTES); + } +#endif // !TARGET_LOONGARCH64 } #ifdef TARGET_ARM @@ -6189,13 +6197,17 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals() stkOffs -= (compCalleeRegsPushed - 2) * REGSIZE_BYTES; } -#elif defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) +#elif defined(TARGET_LOONGARCH64) + + assert(compCalleeRegsPushed >= 2); + +#elif defined(TARGET_RISCV64) // Subtract off FP and RA. assert(compCalleeRegsPushed >= 2); stkOffs -= (compCalleeRegsPushed - 2) * REGSIZE_BYTES; -#else // !TARGET_LOONGARCH64 !TARGET_RISCV64 +#else // !TARGET_RISCV64 #ifdef TARGET_ARM // On ARM32 LR is part of the pushed registers and is always stored at the // top. @@ -6206,7 +6218,7 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals() #endif stkOffs -= compCalleeRegsPushed * REGSIZE_BYTES; -#endif // !TARGET_LOONGARCH64 !TARGET_RISCV64 +#endif // !TARGET_RISCV64 // (2) Account for the remainder of the frame // @@ -6928,10 +6940,10 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals() } #endif // TARGET_ARM64 -#if defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) +#if defined(TARGET_RISCV64) assert(isFramePointerUsed()); // Note that currently we always have a frame pointer stkOffs -= 2 * REGSIZE_BYTES; -#endif // TARGET_LOONGARCH64 || TARGET_RISCV64 +#endif // TARGET_RISCV64 #if FEATURE_FIXED_OUT_ARGS if (lvaOutgoingArgSpaceSize > 0) @@ -6949,9 +6961,14 @@ void Compiler::lvaAssignVirtualFrameOffsetsToLocals() } #endif // FEATURE_FIXED_OUT_ARGS +#ifdef TARGET_LOONGARCH64 + // For LoongArch64, 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) @@ -7803,7 +7820,7 @@ unsigned Compiler::lvaFrameSize(FrameLayoutState curState) if (compFloatingPointUsed) compCalleeRegsPushed += CNT_CALLEE_SAVED_FLOAT; - compCalleeRegsPushed++; // we always push LR/RA. See genPushCalleeSavedRegisters + compCalleeRegsPushed++; // we always push LR or RA. See genPushCalleeSavedRegisters #elif defined(TARGET_AMD64) if (compFloatingPointUsed) { @@ -7840,7 +7857,7 @@ unsigned Compiler::lvaFrameSize(FrameLayoutState curState) { calleeSavedRegMaxSz += CALLEE_SAVED_FLOAT_MAXSZ; } - calleeSavedRegMaxSz += REGSIZE_BYTES; // we always push LR/RA. See genPushCalleeSavedRegisters + calleeSavedRegMaxSz += REGSIZE_BYTES; // we always push LR or RA. See genPushCalleeSavedRegisters #endif result = compLclFrameSize + calleeSavedRegMaxSz; @@ -7927,7 +7944,7 @@ int Compiler::lvaToCallerSPRelativeOffset(int offset, bool isFpBased, bool forRo offset += codeGen->genCallerSPtoInitialSPdelta(); } -#if defined(TARGET_AMD64) || defined(TARGET_ARM64) +#if defined(TARGET_AMD64) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) if (forRootFrame && opts.IsOSR()) { const PatchpointInfo* const ppInfo = info.compPatchpointInfo; @@ -7946,7 +7963,7 @@ int Compiler::lvaToCallerSPRelativeOffset(int offset, bool isFpBased, bool forRo // const int adjustment = ppInfo->TotalFrameSize() + REGSIZE_BYTES; -#elif defined(TARGET_ARM64) +#elif defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) const int adjustment = ppInfo->TotalFrameSize(); #endif diff --git a/src/coreclr/jit/likelyclass.cpp b/src/coreclr/jit/likelyclass.cpp index ed877fdc5da8fa..86f4784b7e6a81 100644 --- a/src/coreclr/jit/likelyclass.cpp +++ b/src/coreclr/jit/likelyclass.cpp @@ -121,6 +121,11 @@ static unsigned getLikelyClassesOrMethods(LikelyClassMethodRecord* int32_t ilOffset, bool types) { + if (maxLikelyClasses == 0) + { + return 0; + } + ICorJitInfo::PgoInstrumentationKind histogramKind = types ? ICorJitInfo::PgoInstrumentationKind::HandleHistogramTypes : ICorJitInfo::PgoInstrumentationKind::HandleHistogramMethods; @@ -235,6 +240,12 @@ static unsigned getLikelyClassesOrMethods(LikelyClassMethodRecord* } } + if (knownHandles == 0) + { + // We don't have known handles + return 0; + } + // sort by m_count (descending) jitstd::sort(sortedEntries, sortedEntries + knownHandles, [](const LikelyClassMethodHistogramEntry& h1, @@ -244,12 +255,27 @@ static unsigned getLikelyClassesOrMethods(LikelyClassMethodRecord* const UINT32 numberOfClasses = min(knownHandles, maxLikelyClasses); + UINT32 totalLikelihood = 0; for (size_t hIdx = 0; hIdx < numberOfClasses; hIdx++) { LikelyClassMethodHistogramEntry const hc = sortedEntries[hIdx]; pLikelyEntries[hIdx].handle = hc.m_handle; pLikelyEntries[hIdx].likelihood = hc.m_count * 100 / h.m_totalCount; + totalLikelihood += pLikelyEntries[hIdx].likelihood; + } + + assert(totalLikelihood <= 100); + + // Distribute the rounding error and just apply it to the first entry. + // Assume that there is no error If we have unknown handles. + if (numberOfClasses == h.m_totalCount) + { + assert(numberOfClasses > 0); + assert(totalLikelihood > 0); + pLikelyEntries[0].likelihood += 100 - totalLikelihood; + assert(pLikelyEntries[0].likelihood <= 100); } + return numberOfClasses; } } diff --git a/src/coreclr/jit/lower.h b/src/coreclr/jit/lower.h index aabb28592803be..2afbeb1b23df54 100644 --- a/src/coreclr/jit/lower.h +++ b/src/coreclr/jit/lower.h @@ -110,6 +110,9 @@ class Lowering final : public Phase #ifdef FEATURE_HW_INTRINSICS void ContainCheckHWIntrinsicAddr(GenTreeHWIntrinsic* node, GenTree* addr); void ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node); +#ifdef TARGET_XARCH + void TryFoldCnsVecForEmbeddedBroadcast(GenTreeHWIntrinsic* parentNode, GenTreeVecCon* childNode); +#endif // TARGET_XARCH #endif // FEATURE_HW_INTRINSICS #ifdef DEBUG @@ -352,11 +355,11 @@ class Lowering final : public Phase GenTree* LowerHWIntrinsic(GenTreeHWIntrinsic* node); void LowerHWIntrinsicCC(GenTreeHWIntrinsic* node, NamedIntrinsic newIntrinsicId, GenCondition condition); GenTree* LowerHWIntrinsicCmpOp(GenTreeHWIntrinsic* node, genTreeOps cmpOp); - GenTree* LowerHWIntrinsicCmpOpWithKReg(GenTreeHWIntrinsic* node); GenTree* LowerHWIntrinsicCreate(GenTreeHWIntrinsic* node); GenTree* LowerHWIntrinsicDot(GenTreeHWIntrinsic* node); #if defined(TARGET_XARCH) void LowerFusedMultiplyAdd(GenTreeHWIntrinsic* node); + GenTree* LowerHWIntrinsicWithAvx512Mask(GenTreeHWIntrinsic* node); GenTree* LowerHWIntrinsicToScalar(GenTreeHWIntrinsic* node); GenTree* LowerHWIntrinsicGetElement(GenTreeHWIntrinsic* node); GenTree* LowerHWIntrinsicCndSel(GenTreeHWIntrinsic* node); diff --git a/src/coreclr/jit/lowerriscv64.cpp b/src/coreclr/jit/lowerriscv64.cpp index 8bd0a8003fe34f..17b1ca46b37543 100644 --- a/src/coreclr/jit/lowerriscv64.cpp +++ b/src/coreclr/jit/lowerriscv64.cpp @@ -140,7 +140,7 @@ GenTree* Lowering::LowerJTrue(GenTreeOp* jtrue) if (op->OperIsCompare() && !varTypeIsFloating(op->gtGetOp1())) { - // We do not expect any other relops on LA64 + // We do not expect any other relops on RISCV64 assert(op->OperIs(GT_EQ, GT_NE, GT_LT, GT_LE, GT_GE, GT_GT)); cond = GenCondition::FromRelop(op); diff --git a/src/coreclr/jit/lowerxarch.cpp b/src/coreclr/jit/lowerxarch.cpp index 4b516a5b0ce36a..24a581adf6d431 100644 --- a/src/coreclr/jit/lowerxarch.cpp +++ b/src/coreclr/jit/lowerxarch.cpp @@ -894,12 +894,20 @@ void Lowering::LowerHWIntrinsicCC(GenTreeHWIntrinsic* node, NamedIntrinsic newIn } break; - case NI_AVX512F_KORTEST: case NI_SSE41_PTEST: case NI_AVX_PTEST: + { // If we need the Carry flag then we can't swap operands. canSwapOperands = (cc == nullptr) || cc->gtCondition.Is(GenCondition::EQ, GenCondition::NE); break; + } + + case NI_AVX512F_KORTEST: + { + // TODO-XARCH-AVX512 remove the KORTEST check when its promoted to 2 proper arguments + assert(HWIntrinsicInfo::lookupNumArgs(newIntrinsicId) == 1); + break; + } default: unreached(); @@ -1166,28 +1174,16 @@ GenTree* Lowering::LowerHWIntrinsic(GenTreeHWIntrinsic* node) case NI_Vector128_op_Equality: case NI_Vector256_op_Equality: + case NI_Vector512_op_Equality: { return LowerHWIntrinsicCmpOp(node, GT_EQ); } case NI_Vector128_op_Inequality: case NI_Vector256_op_Inequality: - { - return LowerHWIntrinsicCmpOp(node, GT_NE); - } - - case NI_Vector512_GreaterThanAll: - case NI_Vector512_GreaterThanAny: - case NI_Vector512_GreaterThanOrEqualAll: - case NI_Vector512_GreaterThanOrEqualAny: - case NI_Vector512_LessThanAll: - case NI_Vector512_LessThanAny: - case NI_Vector512_LessThanOrEqualAll: - case NI_Vector512_LessThanOrEqualAny: - case NI_Vector512_op_Equality: case NI_Vector512_op_Inequality: { - return LowerHWIntrinsicCmpOpWithKReg(node); + return LowerHWIntrinsicCmpOp(node, GT_NE); } case NI_Vector128_ToScalar: @@ -1614,6 +1610,32 @@ GenTree* Lowering::LowerHWIntrinsic(GenTreeHWIntrinsic* node) LowerFusedMultiplyAdd(node); break; + case NI_AVX512F_CompareEqual: + case NI_AVX512F_CompareGreaterThan: + case NI_AVX512F_CompareGreaterThanOrEqual: + case NI_AVX512F_CompareLessThan: + case NI_AVX512F_CompareLessThanOrEqual: + case NI_AVX512F_CompareNotEqual: + case NI_AVX512F_VL_CompareGreaterThan: + case NI_AVX512F_VL_CompareGreaterThanOrEqual: + case NI_AVX512F_VL_CompareLessThan: + case NI_AVX512F_VL_CompareLessThanOrEqual: + case NI_AVX512F_VL_CompareNotEqual: + case NI_AVX512BW_CompareEqual: + case NI_AVX512BW_CompareGreaterThan: + case NI_AVX512BW_CompareGreaterThanOrEqual: + case NI_AVX512BW_CompareLessThan: + case NI_AVX512BW_CompareLessThanOrEqual: + case NI_AVX512BW_CompareNotEqual: + case NI_AVX512BW_VL_CompareGreaterThan: + case NI_AVX512BW_VL_CompareGreaterThanOrEqual: + case NI_AVX512BW_VL_CompareLessThan: + case NI_AVX512BW_VL_CompareLessThanOrEqual: + case NI_AVX512BW_VL_CompareNotEqual: + { + return LowerHWIntrinsicWithAvx512Mask(node); + } + default: break; } @@ -1638,7 +1660,8 @@ GenTree* Lowering::LowerHWIntrinsicCmpOp(GenTreeHWIntrinsic* node, genTreeOps cm var_types simdType = Compiler::getSIMDTypeForSize(simdSize); assert((intrinsicId == NI_Vector128_op_Equality) || (intrinsicId == NI_Vector128_op_Inequality) || - (intrinsicId == NI_Vector256_op_Equality) || (intrinsicId == NI_Vector256_op_Inequality)); + (intrinsicId == NI_Vector256_op_Equality) || (intrinsicId == NI_Vector256_op_Inequality) || + (intrinsicId == NI_Vector512_op_Equality) || (intrinsicId == NI_Vector512_op_Inequality)); assert(varTypeIsSIMD(simdType)); assert(varTypeIsArithmetic(simdBaseType)); @@ -1655,8 +1678,9 @@ GenTree* Lowering::LowerHWIntrinsicCmpOp(GenTreeHWIntrinsic* node, genTreeOps cm GenTree* op2 = node->Op(2); GenCondition cmpCnd = (cmpOp == GT_EQ) ? GenCondition::EQ : GenCondition::NE; - if (!varTypeIsFloating(simdBaseType) && op2->IsVectorZero() && - comp->compOpportunisticallyDependsOn(InstructionSet_SSE41)) + if (!varTypeIsFloating(simdBaseType) && (simdSize != 64) && op2->IsVectorZero() && + comp->compOpportunisticallyDependsOn(InstructionSet_SSE41) && + !op1->OperIsHWIntrinsic(NI_AVX512F_ConvertMaskToVector)) { // On SSE4.1 or higher we can optimize comparisons against zero to // just use PTEST. We can't support it for floating-point, however, @@ -1681,14 +1705,269 @@ GenTree* Lowering::LowerHWIntrinsicCmpOp(GenTreeHWIntrinsic* node, genTreeOps cm } else { + assert(simdSize == 16); + // TODO-Review: LowerHWIntrinsicCC resets the id again, so why is this needed? node->ChangeHWIntrinsicId(NI_SSE41_TestZ); LowerHWIntrinsicCC(node, NI_SSE41_PTEST, cmpCnd); } - return node->gtNext; + return LowerNode(node); + } + + // TODO-XARCH-AVX512: We should handle TYP_SIMD12 here under the EVEX path, but doing + // so will require us to account for the unused 4th element. + + if ((simdType != TYP_SIMD12) && comp->IsBaselineVector512IsaSupported()) + { + // The EVEX encoded versions of the comparison instructions all return a kmask + // + // For the comparisons against zero that we normally optimize to use `PTEST` we + // have to make a decision to use EVEX and emit 2 instructions (vpcmp + kortest) + // or to continue emitting PTEST and hope that the register allocator isn't limited + // by it not supporting the extended register set. + // + // Ideally we'd opt to not use PTEST when EVEX is available, This would be done so we can + // best take advantage of EVEX exclusive features such as embedded broadcast and the + // 16 additional registers. In many cases this allows for overall denser codegen where + // we are doing more in the same number of bytes, even though the individual instruction + // is 1-2 bytes larger. Even though there may be cases where continuing to use PTEST for select- + // 128/256-bit code paths would still be beneficial, the additional complexity required + // to detect and account for those differences is not likely to be worth the tradeoff. + // + // TODO-XARCH-AVX512: Given the above don't emit the PTEST path above when AVX-512 is available + // This will require exposing `NI_AVX512F_TestZ` so that we can keep codegen optimized to just + // `vptestm` followed by `kortest`. This will be one instruction more than just `vptest` but + // it has the advantages detailed above. + // + // For other comparisons, using EVEX allows us to avoid leaving the SIMD domain, avoids + // needing to use a general-purpose register, and allows us to generate less instructions. + + GenTree* nextNode = node->gtNext; + + NamedIntrinsic maskIntrinsicId = NI_AVX512F_CompareEqualMask; + uint32_t count = simdSize / genTypeSize(simdBaseType); + + // KORTEST does a bitwise or on the result and sets ZF if it is zero and CF if it is all + // bits set. Because of this, when we have at least 8 elements to compare we can use a + // normal comparison alongside CF. + // + // That is, if the user wants `x == y`, we can keep it as `mask = (x == y)` and then emit + // `kortest mask, mask` and check `CF == 1`. This will be true if all elements matched and + // false otherwise. Things work out nicely and we keep readable disasm. + // + // Likewise, if the user wants `x != y`, we can keep it as `mask = (x != y)` and then emit + // `kortest mask, mask` and check `ZF != 0`. This will be true if any elements mismatched. + // + // However, if we have less than 8 elements then we have to change it up since we have less + // than 8 bits in the output mask and unused bits will be set to 0. This occurs for 32-bit + // for Vector128 and and 64-bit elements when using either Vector128 or Vector256. + // + // To account for this, we will invert the comparison being done. So if the user wants + // `x == y`, we will instead emit `mask = (x != y)`, we will still emit `kortest mask, mask`, + // but we will then check for `ZF == 0`. This works since that equates to all elements being equal + // + // Likewise for `x != y` we will instead emit `mask = (x == y)`, then `kortest mask, mask`, + // and will then check for `CF == 0` which equates to one or more elements not being equal + + // The scenarios we have to for a full mask are: + // * No matches: 0000_0000 - ZF == 1, CF == 0 + // * Partial matches: 0000_1111 - ZF == 0, CF == 0 + // * All matches: 1111_1111 - ZF == 0, CF == 1 + // + // The scenarios we have to for a partial mask are: + // * No matches: 0000_0000 - ZF == 1, CF == 0 + // * Partial matches: 0000_0011 - ZF == 0, CF == 0 + // * All matches: 0000_1111 - ZF == 0, CF == 0 + // + // When we have less than a full mask worth of elements, we need to account for the upper + // bits being implicitly zero. To do that, we may need to invert the comparison. + // + // By inverting the comparison we'll get: + // * All matches: 0000_0000 - ZF == 1, CF == 0 + // * Partial matches: 0000_0011 - ZF == 0, CF == 0 + // * No matches: 0000_1111 - ZF == 0, CF == 0 + // + // 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()) + { + // We want to specially handle the common cases of `mask op Zero` and `mask op AllBitsSet` + // + // These get created for the various `gtNewSimdCmpOpAnyNode` and `gtNewSimdCmpOpAllNode` + // scenarios and we want to ensure they still get "optimal" codegen. To handle that, we + // simply consume the mask directly and preserve the intended comparison by tweaking the + // compare condition passed down into `KORTEST` + + GenTreeHWIntrinsic* maskNode = op1->AsHWIntrinsic()->Op(1)->AsHWIntrinsic(); + assert(maskNode->TypeIs(TYP_MASK)); + + bool isHandled = false; + GenTreeVecCon* vecCon = op2->AsVecCon(); + + if (vecCon->IsZero()) + { + // We have `mask == Zero` which is the same as checking that nothing in the mask + // is set. This scenario can be handled by `kortest` and then checking that `ZF == 1` + // + // -or- + // + // We have `mask != Zero` which is the same as checking that something in the mask + // is set. This scenario can be handled by `kortest` and then checking that `ZF == 0` + // + // Since this is the default state for `CompareEqualMask` + `GT_EQ`/`GT_NE`, there is nothing + // for us to change. This also applies to cases where we have less than a full mask of + // elements since the upper mask bits are implicitly zero. + + isHandled = true; + } + else if (vecCon->IsAllBitsSet()) + { + // We have `mask == AllBitsSet` which is the same as checking that everything in the mask + // is set. This scenario can be handled by `kortest` and then checking that `CF == 1` for + // a full mask and checking `ZF == 1` for a partial mask using an inverted comparison + // + // -or- + // + // We have `mask != AllBitsSet` which is the same as checking that something in the mask + // is set. This scenario can be handled by `kortest` and then checking that `CF == 0` for + // a full mask and checking `ZF != 0` for a partial mask using an inverted comparison + + if (count < 8) + { + assert((count == 1) || (count == 2) || (count == 4)); + + switch (maskNode->GetHWIntrinsicId()) + { + case NI_AVX512F_CompareEqualMask: + { + maskIntrinsicId = NI_AVX512F_CompareNotEqualMask; + break; + } + + case NI_AVX512F_CompareGreaterThanMask: + { + maskIntrinsicId = NI_AVX512F_CompareLessThanOrEqualMask; + break; + } + + case NI_AVX512F_CompareGreaterThanOrEqualMask: + { + maskIntrinsicId = NI_AVX512F_CompareLessThanMask; + break; + } + + case NI_AVX512F_CompareLessThanMask: + { + maskIntrinsicId = NI_AVX512F_CompareGreaterThanOrEqualMask; + break; + } + + case NI_AVX512F_CompareLessThanOrEqualMask: + { + maskIntrinsicId = NI_AVX512F_CompareGreaterThanMask; + break; + } + + case NI_AVX512F_CompareNotEqualMask: + { + maskIntrinsicId = NI_AVX512F_CompareEqualMask; + break; + } + + default: + { + unreached(); + } + } + + maskNode->ChangeHWIntrinsicId(maskIntrinsicId); + } + else if (cmpOp == GT_EQ) + { + cmpCnd = GenCondition::C; + } + else + { + cmpCnd = GenCondition::NC; + } + isHandled = true; + } + + if (isHandled) + { + LIR::Use use; + if (BlockRange().TryGetUse(node, &use)) + { + use.ReplaceWith(maskNode); + } + else + { + maskNode->SetUnusedValue(); + } + + BlockRange().Remove(op2); + BlockRange().Remove(op1); + BlockRange().Remove(node); + + node = maskNode; + } + } + + if (node->gtType != TYP_MASK) + { + // We have `x == y` or `x != y` both of which where we want to find `AllBitsSet` in the mask since + // we can directly do the relevant comparison. Given the above tables then when we have a full mask + // we can simply check against `CF == 1` for `op_Equality` and `ZF == 0` for `op_Inequality`. + // + // For a partial mask, we need to invert the `op_Equality` comparisons which means that we now need + // to check for `ZF == 1` (we're looking for `AllBitsSet`, that is `all match`). For `op_Inequality` + // we can keep things as is since we're looking for `any match` and just want to check `ZF == 0` + + if (count < 8) + { + assert((count == 1) || (count == 2) || (count == 4)); + maskIntrinsicId = NI_AVX512F_CompareNotEqualMask; + } + else + { + assert((count == 8) || (count == 16) || (count == 32) || (count == 64)); + + if (cmpOp == GT_EQ) + { + cmpCnd = GenCondition::C; + } + else + { + maskIntrinsicId = NI_AVX512F_CompareNotEqualMask; + } + } + + node->gtType = TYP_MASK; + node->ChangeHWIntrinsicId(maskIntrinsicId); + + LowerNode(node); + } + + LIR::Use use; + if (BlockRange().TryGetUse(node, &use)) + { + GenTreeHWIntrinsic* cc; + + cc = comp->gtNewSimdHWIntrinsicNode(simdType, node, NI_AVX512F_KORTEST, simdBaseJitType, simdSize); + BlockRange().InsertBefore(nextNode, cc); + + use.ReplaceWith(cc); + LowerHWIntrinsicCC(cc, NI_AVX512F_KORTEST, cmpCnd); + + nextNode = cc->gtNext; + } + return nextNode; } + assert(simdSize != 64); + NamedIntrinsic cmpIntrinsic; CorInfoType cmpJitType; NamedIntrinsic mskIntrinsic; @@ -1728,11 +2007,11 @@ GenTree* Lowering::LowerHWIntrinsicCmpOp(GenTreeHWIntrinsic* node, genTreeOps cm case TYP_ULONG: { mskJitType = CORINFO_TYPE_UBYTE; + cmpJitType = simdBaseJitType; if (simdSize == 32) { cmpIntrinsic = NI_AVX2_CompareEqual; - cmpJitType = simdBaseJitType; mskIntrinsic = NI_AVX2_MoveMask; mskConstant = -1; } @@ -1743,7 +2022,6 @@ GenTree* Lowering::LowerHWIntrinsicCmpOp(GenTreeHWIntrinsic* node, genTreeOps cm if (comp->compOpportunisticallyDependsOn(InstructionSet_SSE41)) { cmpIntrinsic = NI_SSE41_CompareEqual; - cmpJitType = simdBaseJitType; } else { @@ -1855,80 +2133,6 @@ GenTree* Lowering::LowerHWIntrinsicCmpOp(GenTreeHWIntrinsic* node, genTreeOps cm return LowerNode(node); } -//---------------------------------------------------------------------------------------------- -// Lowering::LowerHWIntrinsicCmpOpWithKReg: Lowers a Vector512 comparison intrinsic -// -// Arguments: -// node - The hardware intrinsic node. -// -GenTree* Lowering::LowerHWIntrinsicCmpOpWithKReg(GenTreeHWIntrinsic* node) -{ - NamedIntrinsic intrinsicId = node->GetHWIntrinsicId(); - CorInfoType simdBaseJitType = node->GetSimdBaseJitType(); - var_types simdBaseType = node->GetSimdBaseType(); - unsigned simdSize = node->GetSimdSize(); - var_types simdType = Compiler::getSIMDTypeForSize(simdSize); - - assert((intrinsicId == NI_Vector512_GreaterThanAll) || (intrinsicId == NI_Vector512_GreaterThanOrEqualAll) || - (intrinsicId == NI_Vector512_LessThanAll) || (intrinsicId == NI_Vector512_LessThanOrEqualAll) || - (intrinsicId == NI_Vector512_op_Equality) || (intrinsicId == NI_Vector512_op_Inequality)); - - assert(varTypeIsSIMD(simdType)); - assert(varTypeIsArithmetic(simdBaseType)); - assert(simdSize == 64); - assert(node->gtType == TYP_BOOL); - - NamedIntrinsic newIntrinsicId = NI_Illegal; - switch (intrinsicId) - { - case NI_Vector512_GreaterThanAll: - { - newIntrinsicId = NI_AVX512F_CompareGreaterThanSpecial; - break; - } - case NI_Vector512_GreaterThanOrEqualAll: - { - newIntrinsicId = NI_AVX512F_CompareGreaterThanOrEqualSpecial; - break; - } - case NI_Vector512_LessThanAll: - { - newIntrinsicId = NI_AVX512F_CompareLessThanSpecial; - break; - } - case NI_Vector512_LessThanOrEqualAll: - { - newIntrinsicId = NI_AVX512F_CompareLessThanOrEqualSpecial; - break; - } - case NI_Vector512_op_Equality: - case NI_Vector512_op_Inequality: - { - newIntrinsicId = NI_AVX512F_CompareEqualSpecial; - break; - } - - default: - { - assert(false); - break; - } - } - - GenTree* op1 = node->Op(1); - GenTree* op2 = node->Op(2); - - GenTree* cmp = comp->gtNewSimdHWIntrinsicNode(TYP_MASK, op1, op2, newIntrinsicId, simdBaseJitType, simdSize); - BlockRange().InsertBefore(node, cmp); - LowerNode(cmp); - - node->ResetHWIntrinsicId(NI_AVX512F_KORTEST, cmp); - GenCondition cmpCnd = (intrinsicId != NI_Vector512_op_Inequality) ? GenCondition::C : GenCondition::NC; - LowerHWIntrinsicCC(node, NI_AVX512F_KORTEST, cmpCnd); - - return node->gtNext; -} - //---------------------------------------------------------------------------------------------- // Lowering::LowerHWIntrinsicCndSel: Lowers a Vector128 or Vector256 Conditional Select call // @@ -2312,12 +2516,13 @@ GenTree* Lowering::LowerHWIntrinsicCreate(GenTreeHWIntrinsic* node) node->ResetHWIntrinsicId(NI_AVX512BW_BroadcastScalarToVector512, tmp1); break; } + case TYP_INT: case TYP_UINT: - case TYP_LONG: - case TYP_ULONG: case TYP_FLOAT: case TYP_DOUBLE: + case TYP_LONG: + case TYP_ULONG: { assert(comp->compIsaSupportedDebugOnly(InstructionSet_AVX512F)); node->ResetHWIntrinsicId(NI_AVX512F_BroadcastScalarToVector512, tmp1); @@ -2353,7 +2558,6 @@ GenTree* Lowering::LowerHWIntrinsicCreate(GenTreeHWIntrinsic* node) LowerNode(tmp1); node->ResetHWIntrinsicId(NI_AVX2_BroadcastScalarToVector256, tmp1); - return LowerNode(node); } @@ -2428,7 +2632,6 @@ GenTree* Lowering::LowerHWIntrinsicCreate(GenTreeHWIntrinsic* node) // return Avx2.BroadcastScalarToVector128(tmp1); node->ChangeHWIntrinsicId(NI_AVX2_BroadcastScalarToVector128, tmp1); - return LowerNode(node); } @@ -4826,6 +5029,125 @@ GenTree* Lowering::LowerHWIntrinsicDot(GenTreeHWIntrinsic* node) } } +//---------------------------------------------------------------------------------------------- +// Lowering::LowerHWIntrinsicWithAvx512Mask: Lowers a HWIntrinsic node that utilizes the AVX512 KMASK registers +// +// Arguments: +// node - The hardware intrinsic node. +// +GenTree* Lowering::LowerHWIntrinsicWithAvx512Mask(GenTreeHWIntrinsic* node) +{ + NamedIntrinsic intrinsicId = node->GetHWIntrinsicId(); + CorInfoType simdBaseJitType = node->GetSimdBaseJitType(); + var_types simdBaseType = node->GetSimdBaseType(); + unsigned simdSize = node->GetSimdSize(); + var_types simdType = Compiler::getSIMDTypeForSize(simdSize); + + assert(varTypeIsSIMD(simdType)); + assert(varTypeIsArithmetic(simdBaseType)); + assert(simdSize != 0); + + NamedIntrinsic maskIntrinsicId; + + switch (intrinsicId) + { + case NI_AVX512F_CompareEqual: + case NI_AVX512BW_CompareEqual: + { + maskIntrinsicId = NI_AVX512F_CompareEqualMask; + break; + } + + case NI_AVX512F_VL_CompareGreaterThan: + case NI_AVX512BW_VL_CompareGreaterThan: + { + assert(varTypeIsUnsigned(simdBaseType)); + FALLTHROUGH; + } + + case NI_AVX512F_CompareGreaterThan: + case NI_AVX512BW_CompareGreaterThan: + { + maskIntrinsicId = NI_AVX512F_CompareGreaterThanMask; + break; + } + + case NI_AVX512F_VL_CompareGreaterThanOrEqual: + case NI_AVX512BW_VL_CompareGreaterThanOrEqual: + { + assert(!varTypeIsFloating(simdBaseType)); + FALLTHROUGH; + } + + case NI_AVX512F_CompareGreaterThanOrEqual: + case NI_AVX512BW_CompareGreaterThanOrEqual: + { + maskIntrinsicId = NI_AVX512F_CompareGreaterThanOrEqualMask; + break; + } + + case NI_AVX512F_VL_CompareLessThan: + case NI_AVX512BW_VL_CompareLessThan: + { + assert(varTypeIsUnsigned(simdBaseType)); + FALLTHROUGH; + } + + case NI_AVX512F_CompareLessThan: + case NI_AVX512BW_CompareLessThan: + { + maskIntrinsicId = NI_AVX512F_CompareLessThanMask; + break; + } + + case NI_AVX512F_VL_CompareLessThanOrEqual: + case NI_AVX512BW_VL_CompareLessThanOrEqual: + { + assert(!varTypeIsFloating(simdBaseType)); + FALLTHROUGH; + } + + case NI_AVX512F_CompareLessThanOrEqual: + case NI_AVX512BW_CompareLessThanOrEqual: + { + maskIntrinsicId = NI_AVX512F_CompareLessThanOrEqualMask; + break; + } + + case NI_AVX512F_VL_CompareNotEqual: + case NI_AVX512BW_VL_CompareNotEqual: + { + assert(!varTypeIsFloating(simdBaseType)); + FALLTHROUGH; + } + + case NI_AVX512F_CompareNotEqual: + case NI_AVX512BW_CompareNotEqual: + { + maskIntrinsicId = NI_AVX512F_CompareNotEqualMask; + break; + } + + default: + { + unreached(); + } + } + + node->gtType = TYP_MASK; + node->ChangeHWIntrinsicId(maskIntrinsicId); + + LIR::Use use; + if (BlockRange().TryGetUse(node, &use)) + { + GenTree* maskToVector = + comp->gtNewSimdHWIntrinsicNode(simdType, node, NI_AVX512F_ConvertMaskToVector, simdBaseJitType, simdSize); + BlockRange().InsertAfter(node, maskToVector); + use.ReplaceWith(maskToVector); + } + return LowerNode(node); +} + //---------------------------------------------------------------------------------------------- // Lowering::LowerHWIntrinsicToScalar: Lowers a Vector128 or Vector256 ToScalar call // @@ -7578,7 +7900,6 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* parentNode, GenTre canBeContained = !vecCon->IsAllBitsSet() && !vecCon->IsZero(); } } - return canBeContained; } @@ -7601,7 +7922,7 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* parentNode, GenTre GenTree* op1 = hwintrinsic->Op(1); - if (IsSafeToContainMem(parentNode, hwintrinsic, op1)) + if (IsInvariantInRange(op1, parentNode, hwintrinsic)) { if (op1->isContained()) { @@ -7699,6 +8020,51 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* parentNode, GenTre return false; } + case NI_SSE3_MoveAndDuplicate: + case NI_AVX2_BroadcastScalarToVector128: + case NI_AVX2_BroadcastScalarToVector256: + case NI_AVX512F_BroadcastScalarToVector512: + { + // make the broadcast node containable when embedded broadcast can be enabled. + if (intrinsicId == NI_SSE3_MoveAndDuplicate) + { + // NI_SSE3_MoveAndDuplicate is for Vector128 only. + assert(hwintrinsic->GetSimdBaseType() == TYP_DOUBLE); + } + + if (comp->compOpportunisticallyDependsOn(InstructionSet_AVX512F_VL) && + parentNode->OperIsEmbBroadcastCompatible()) + { + GenTree* broadcastOperand = hwintrinsic->Op(1); + + if (broadcastOperand->OperIsHWIntrinsic()) + { + GenTreeHWIntrinsic* hwintrinsicOperand = broadcastOperand->AsHWIntrinsic(); + + if (hwintrinsicOperand->OperIsCreateScalarUnsafe()) + { + // CreateScalarUnsafe can contain non-memory operands such as enregistered + // locals, so we want to check if its operand is containable instead. This + // will result in such enregistered locals returning `false`. + broadcastOperand = hwintrinsicOperand->Op(1); + } + } + + bool childSupportsRegOptional; + if (IsContainableHWIntrinsicOp(hwintrinsic, broadcastOperand, &childSupportsRegOptional)) + { + return true; + } + } + return false; + } + + case NI_AVX_BroadcastScalarToVector128: + case NI_AVX_BroadcastScalarToVector256: + { + return parentNode->OperIsEmbBroadcastCompatible(); + } + default: { assert(!childNode->isContainableHWIntrinsic()); @@ -7707,6 +8073,153 @@ bool Lowering::IsContainableHWIntrinsicOp(GenTreeHWIntrinsic* parentNode, GenTre } } +//---------------------------------------------------------------------------------------------- +// TryFoldCnsVecForEmbeddedBroadcast: +// Unfold the eligible constant vector when embedded broadcast is +// available. +// +// Arguments: +// parentNode - The hardware intrinsic node +// childNode - The operand node to try contain +// +void Lowering::TryFoldCnsVecForEmbeddedBroadcast(GenTreeHWIntrinsic* parentNode, GenTreeVecCon* childNode) +{ + assert(!childNode->IsAllBitsSet()); + assert(!childNode->IsZero()); + var_types simdType = parentNode->TypeGet(); + var_types simdBaseType = parentNode->GetSimdBaseType(); + CorInfoType simdBaseJitType = parentNode->GetSimdBaseJitType(); + bool isCreatedFromScalar = true; + int elementCount = GenTreeVecCon::ElementCount(genTypeSize(simdType), simdBaseType); + switch (simdBaseType) + { + case TYP_FLOAT: + case TYP_INT: + case TYP_UINT: + { + uint32_t firstElement = static_cast(childNode->gtSimdVal.u32[0]); + for (int i = 1; i < elementCount; i++) + { + uint32_t elementToCheck = static_cast(childNode->gtSimdVal.u32[i]); + if (firstElement != elementToCheck) + { + isCreatedFromScalar = false; + break; + } + } + break; + } + + case TYP_DOUBLE: +#if defined(TARGET_AMD64) + case TYP_LONG: + case TYP_ULONG: +#endif // TARGET_AMD64 + { + uint64_t firstElement = static_cast(childNode->gtSimdVal.u64[0]); + for (int i = 1; i < elementCount; i++) + { + uint64_t elementToCheck = static_cast(childNode->gtSimdVal.u64[i]); + if (firstElement != elementToCheck) + { + isCreatedFromScalar = false; + break; + } + } + break; + } + + default: + isCreatedFromScalar = false; + break; + } + if (isCreatedFromScalar) + { + NamedIntrinsic broadcastName = NI_AVX2_BroadcastScalarToVector128; + if (simdType == TYP_SIMD32) + { + broadcastName = NI_AVX2_BroadcastScalarToVector256; + } + else if (simdType == TYP_SIMD64) + { + broadcastName = NI_AVX512F_BroadcastScalarToVector512; + } + else + { + assert(simdType == TYP_SIMD16); + } + GenTree* constScalar = nullptr; + switch (simdBaseType) + { + case TYP_FLOAT: + { + float scalar = static_cast(childNode->gtSimdVal.f32[0]); + constScalar = comp->gtNewDconNode(scalar, simdBaseType); + break; + } + case TYP_DOUBLE: + { + double scalar = static_cast(childNode->gtSimdVal.f64[0]); + constScalar = comp->gtNewDconNode(scalar, simdBaseType); + break; + } + case TYP_INT: + { + int32_t scalar = static_cast(childNode->gtSimdVal.i32[0]); + constScalar = comp->gtNewIconNode(scalar, simdBaseType); + break; + } + case TYP_UINT: + { + uint32_t scalar = static_cast(childNode->gtSimdVal.u32[0]); + constScalar = comp->gtNewIconNode(scalar, TYP_INT); + break; + } +#if defined(TARGET_AMD64) + case TYP_LONG: + { + int64_t scalar = static_cast(childNode->gtSimdVal.i64[0]); + constScalar = comp->gtNewIconNode(scalar, simdBaseType); + break; + } + case TYP_ULONG: + { + uint64_t scalar = static_cast(childNode->gtSimdVal.u64[0]); + constScalar = comp->gtNewIconNode(scalar, TYP_LONG); + break; + } +#endif // TARGET_AMD64 + default: + unreached(); + } + GenTreeHWIntrinsic* createScalar = + comp->gtNewSimdHWIntrinsicNode(TYP_SIMD16, constScalar, NI_Vector128_CreateScalarUnsafe, simdBaseJitType, + 16); + GenTreeHWIntrinsic* broadcastNode = comp->gtNewSimdHWIntrinsicNode(simdType, createScalar, broadcastName, + simdBaseJitType, genTypeSize(simdType)); + BlockRange().InsertBefore(childNode, broadcastNode); + BlockRange().InsertBefore(broadcastNode, createScalar); + BlockRange().InsertBefore(createScalar, constScalar); + LIR::Use use; + BlockRange().TryGetUse(childNode, &use); + use.ReplaceWith(broadcastNode); + BlockRange().Remove(childNode); + LowerNode(createScalar); + LowerNode(broadcastNode); + if (varTypeIsFloating(simdBaseType)) + { + MakeSrcContained(broadcastNode, createScalar); + } + else if (constScalar->TypeIs(TYP_INT, TYP_UINT, TYP_LONG, TYP_ULONG)) + { + MakeSrcContained(broadcastNode, constScalar); + } + MakeSrcContained(parentNode, broadcastNode); + return; + } + MakeSrcContained(parentNode, childNode); +} + //---------------------------------------------------------------------------------------------- // ContainCheckHWIntrinsicAddr: Perform containment analysis for an address operand of a hardware // intrinsic node. @@ -8015,13 +8528,29 @@ void Lowering::ContainCheckHWIntrinsic(GenTreeHWIntrinsic* node) if (IsContainableHWIntrinsicOp(node, op2, &supportsOp2RegOptional)) { - MakeSrcContained(node, op2); + if (op2->OperIs(GT_CNS_VEC) && comp->compOpportunisticallyDependsOn(InstructionSet_AVX512F) && + node->OperIsEmbBroadcastCompatible()) + { + TryFoldCnsVecForEmbeddedBroadcast(node, op2->AsVecCon()); + } + else + { + MakeSrcContained(node, op2); + } } else if ((isCommutative || (intrinsicId == NI_BMI2_MultiplyNoFlags) || (intrinsicId == NI_BMI2_X64_MultiplyNoFlags)) && IsContainableHWIntrinsicOp(node, op1, &supportsOp1RegOptional)) { - MakeSrcContained(node, op1); + if (op1->OperIs(GT_CNS_VEC) && comp->compOpportunisticallyDependsOn(InstructionSet_AVX512F) && + node->OperIsEmbBroadcastCompatible()) + { + TryFoldCnsVecForEmbeddedBroadcast(node, op1->AsVecCon()); + } + else + { + MakeSrcContained(node, op1); + } // Swap the operands here to make the containment checks in codegen significantly simpler std::swap(node->Op(1), node->Op(2)); diff --git a/src/coreclr/jit/lsraxarch.cpp b/src/coreclr/jit/lsraxarch.cpp index 765de402b90e23..08ae13c6cff2f3 100644 --- a/src/coreclr/jit/lsraxarch.cpp +++ b/src/coreclr/jit/lsraxarch.cpp @@ -1166,7 +1166,7 @@ int LinearScan::BuildCall(GenTreeCall* call) // The return value will be on the X87 stack, and we will need to move it. dstCandidates = allRegs(registerType); #else // !TARGET_X86 - dstCandidates = RBM_FLOATRET; + dstCandidates = RBM_FLOATRET; #endif // !TARGET_X86 } else @@ -1378,12 +1378,10 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) { case GenTreeBlk::BlkOpKindUnroll: { -#ifdef TARGET_AMD64 - const bool canUse16BytesSimdMov = !blkNode->IsOnHeapAndContainsReferences(); - const bool willUseSimdMov = canUse16BytesSimdMov && (size >= 16); -#else - const bool willUseSimdMov = (size >= 16); -#endif + const bool canUse16BytesSimdMov = + !blkNode->IsOnHeapAndContainsReferences() && compiler->IsBaselineSimdIsaSupported(); + const bool willUseSimdMov = canUse16BytesSimdMov && (size >= XMM_REGSIZE_BYTES); + if (willUseSimdMov) { buildInternalFloatRegisterDefForNode(blkNode, internalFloatRegCandidates()); @@ -1440,8 +1438,26 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) break; case GenTreeBlk::BlkOpKindUnroll: - if ((size % XMM_REGSIZE_BYTES) != 0) + { + unsigned regSize = compiler->roundDownSIMDSize(size); + unsigned remainder = size; + + if ((size >= regSize) && (regSize > 0)) + { + // We need a float temporary if we're doing SIMD operations + + buildInternalFloatRegisterDefForNode(blkNode, internalFloatRegCandidates()); + SetContainsAVXFlags(size); + + remainder %= regSize; + } + + if ((remainder > 0) && ((regSize == 0) || (isPow2(remainder) && (remainder <= REGSIZE_BYTES)))) { + // We need an int temporary if we're not doing SIMD operations + // or if are but the remainder is a power of 2 and less than the + // size of a register + regMaskTP regMask = availableIntRegs; #ifdef TARGET_X86 if ((size & 1) != 0) @@ -1453,13 +1469,8 @@ int LinearScan::BuildBlockStore(GenTreeBlk* blkNode) #endif internalIntDef = buildInternalIntRegisterDefForNode(blkNode, regMask); } - - if (size >= XMM_REGSIZE_BYTES) - { - buildInternalFloatRegisterDefForNode(blkNode, internalFloatRegCandidates()); - SetContainsAVXFlags(size); - } break; + } case GenTreeBlk::BlkOpKindUnrollMemmove: { diff --git a/src/coreclr/jit/namedintrinsiclist.h b/src/coreclr/jit/namedintrinsiclist.h index 50fb3e3ea214bc..6bc31d315b5c36 100644 --- a/src/coreclr/jit/namedintrinsiclist.h +++ b/src/coreclr/jit/namedintrinsiclist.h @@ -126,11 +126,11 @@ enum NamedIntrinsic : unsigned short #ifdef FEATURE_HW_INTRINSICS NI_HW_INTRINSIC_START, #if defined(TARGET_XARCH) -#define HARDWARE_INTRINSIC(isa, name, size, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \ +#define HARDWARE_INTRINSIC(isa, name, size, numarg, extra, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \ NI_##isa##_##name, #include "hwintrinsiclistxarch.h" #elif defined(TARGET_ARM64) -#define HARDWARE_INTRINSIC(isa, name, size, numarg, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \ +#define HARDWARE_INTRINSIC(isa, name, size, numarg, extra, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \ NI_##isa##_##name, #include "hwintrinsiclistarm64.h" #endif // !defined(TARGET_XARCH) && !defined(TARGET_ARM64) diff --git a/src/coreclr/jit/simd.cpp b/src/coreclr/jit/simd.cpp index 97b7d06e51ebd0..2e10faae2f0188 100644 --- a/src/coreclr/jit/simd.cpp +++ b/src/coreclr/jit/simd.cpp @@ -299,7 +299,10 @@ CorInfoType Compiler::getBaseJitTypeAndSizeOfSIMDType(CORINFO_CLASS_HANDLE typeH JITDUMP(" Found Vector<%s>\n", varTypeName(JitType2PreciseVarType(simdBaseJitType))); size = getVectorTByteLength(); - assert(size != 0); + if (size == 0) + { + return CORINFO_TYPE_UNDEF; + } break; } diff --git a/src/coreclr/jit/simdashwintrinsic.cpp b/src/coreclr/jit/simdashwintrinsic.cpp index 0cb64b37428e37..7f71f1c62ecf8b 100644 --- a/src/coreclr/jit/simdashwintrinsic.cpp +++ b/src/coreclr/jit/simdashwintrinsic.cpp @@ -219,8 +219,14 @@ SimdAsHWIntrinsicClassId SimdAsHWIntrinsicInfo::lookupClassId(Compiler* comp, } #endif // TARGET_XARCH - assert(vectorTByteLength == 16); - return SimdAsHWIntrinsicClassId::VectorT128; + if (vectorTByteLength == 16) + { + return SimdAsHWIntrinsicClassId::VectorT128; + } + else + { + return SimdAsHWIntrinsicClassId::Unknown; + } } break; } diff --git a/src/coreclr/jit/ssabuilder.cpp b/src/coreclr/jit/ssabuilder.cpp index b78786a7fa7de1..774e51ee8f9872 100644 --- a/src/coreclr/jit/ssabuilder.cpp +++ b/src/coreclr/jit/ssabuilder.cpp @@ -143,7 +143,7 @@ SsaBuilder::SsaBuilder(Compiler* pCompiler) // // Return Value: // The number of nodes visited while performing DFS on the graph. - +// int SsaBuilder::TopologicalSort(BasicBlock** postOrder, int count) { Compiler* comp = m_pCompiler; @@ -164,15 +164,14 @@ int SsaBuilder::TopologicalSort(BasicBlock** postOrder, int count) unsigned index = 0; while (true) { - bool isEHsucc = successors.IsNextEHSuccessor(); - BasicBlock* succ = successors.NextSuccessor(comp); + BasicBlock* succ = successors.NextSuccessor(comp); if (succ == nullptr) { break; } - printf("%s%s" FMT_BB, (index++ ? ", " : ""), (isEHsucc ? "[EH]" : ""), succ->bbNum); + printf("%s" FMT_BB, (index++ ? ", " : ""), succ->bbNum); } printf("]\n"); } @@ -210,7 +209,7 @@ int SsaBuilder::TopologicalSort(BasicBlock** postOrder, int count) DBG_SSA_JITDUMP("[SsaBuilder::TopologicalSort] postOrder[%d] = " FMT_BB "\n", postIndex, block->bbNum); postOrder[postIndex] = block; block->bbPostorderNum = postIndex; - postIndex += 1; + postIndex++; } } diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index 573fc0c0d054a3..da623ad9ae63f1 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -8852,7 +8852,65 @@ void ValueNumStore::vnDumpZeroObj(Compiler* comp, VNFuncApp* zeroObj) #endif // DEBUG // Static fields, methods. -static UINT8 vnfOpAttribs[VNF_COUNT]; + +#define ValueNumFuncDef(vnf, arity, commute, knownNonNull, sharedStatic, extra) \ + static_assert((arity) >= 0 || !(extra), "valuenumfuncs.h has EncodesExtraTypeArg==true and arity<0 for " #vnf); +#include "valuenumfuncs.h" + +#ifdef FEATURE_HW_INTRINSICS + +#define HARDWARE_INTRINSIC(isa, name, size, argCount, extra, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \ + static_assert((size) != 0 || !(extra), \ + "hwintrinsicslist.h has EncodesExtraTypeArg==true and size==0 for " #isa " " #name); +#if defined(TARGET_XARCH) +#include "hwintrinsiclistxarch.h" +#elif defined(TARGET_ARM64) +#include "hwintrinsiclistarm64.h" +#else +#error Unsupported platform +#endif + +#endif // FEATURE_HW_INTRINSICS + +/* static */ constexpr uint8_t ValueNumStore::GetOpAttribsForArity(genTreeOps oper, GenTreeOperKind kind) +{ + return ((GenTree::StaticOperIs(oper, GT_SELECT) ? 3 : (((kind & GTK_UNOP) >> 1) | ((kind & GTK_BINOP) >> 1))) + << VNFOA_ArityShift) & + VNFOA_ArityMask; +} + +/* static */ constexpr uint8_t ValueNumStore::GetOpAttribsForGenTree(genTreeOps oper, + bool commute, + bool illegalAsVNFunc, + GenTreeOperKind kind) +{ + return GetOpAttribsForArity(oper, kind) | (static_cast(commute) << VNFOA_CommutativeShift) | + (static_cast(illegalAsVNFunc) << VNFOA_IllegalGenTreeOpShift); +} + +/* static */ constexpr uint8_t ValueNumStore::GetOpAttribsForFunc(int arity, + bool commute, + bool knownNonNull, + bool sharedStatic) +{ + return (static_cast(commute) << VNFOA_CommutativeShift) | + (static_cast(knownNonNull) << VNFOA_KnownNonNullShift) | + (static_cast(sharedStatic) << VNFOA_SharedStaticShift) | + ((static_cast(arity & ~(arity >> 31)) << VNFOA_ArityShift) & VNFOA_ArityMask); +} + +const uint8_t ValueNumStore::s_vnfOpAttribs[VNF_COUNT] = { +#define GTNODE(en, st, cm, ivn, ok) \ + GetOpAttribsForGenTree(static_cast(GT_##en), cm, ivn, static_cast(ok)), +#include "gtlist.h" + + 0, // VNF_Boundary + +#define ValueNumFuncDef(vnf, arity, commute, knownNonNull, sharedStatic, extra) \ + GetOpAttribsForFunc((arity) + static_cast(extra), commute, knownNonNull, sharedStatic), +#include "valuenumfuncs.h" +}; + static genTreeOps genTreeOpsIllegalAsVNFunc[] = {GT_IND, // When we do heap memory. GT_NULLCHECK, GT_QMARK, GT_COLON, GT_LOCKADD, GT_XADD, GT_XCHG, GT_CMPXCHG, GT_LCLHEAP, GT_BOX, GT_XORR, GT_XAND, GT_STORE_DYN_BLK, @@ -8869,15 +8927,10 @@ static genTreeOps genTreeOpsIllegalAsVNFunc[] = {GT_IND, // When we do heap memo // These control-flow operations need no values. GT_JTRUE, GT_RETURN, GT_SWITCH, GT_RETFILT, GT_CKFINITE}; -UINT8* ValueNumStore::s_vnfOpAttribs = nullptr; - -void ValueNumStore::InitValueNumStoreStatics() +void ValueNumStore::ValidateValueNumStoreStatics() { - // Make sure we have the constants right... - assert(unsigned(VNFOA_Arity1) == (1 << VNFOA_ArityShift)); - assert(VNFOA_ArityMask == (VNFOA_MaxArity << VNFOA_ArityShift)); - - s_vnfOpAttribs = &vnfOpAttribs[0]; +#if DEBUG + uint8_t arr[VNF_COUNT] = {}; for (unsigned i = 0; i < GT_COUNT; i++) { genTreeOps gtOper = static_cast(i); @@ -8895,11 +8948,11 @@ void ValueNumStore::InitValueNumStoreStatics() arity = 3; } - vnfOpAttribs[i] |= ((arity << VNFOA_ArityShift) & VNFOA_ArityMask); + arr[i] |= ((arity << VNFOA_ArityShift) & VNFOA_ArityMask); if (GenTree::OperIsCommutative(gtOper)) { - vnfOpAttribs[i] |= VNFOA_Commutative; + arr[i] |= VNFOA_Commutative; } } @@ -8907,25 +8960,24 @@ void ValueNumStore::InitValueNumStoreStatics() int vnfNum = VNF_Boundary + 1; // The macro definition below will update this after using it. -#define ValueNumFuncDef(vnf, arity, commute, knownNonNull, sharedStatic) \ +#define ValueNumFuncDef(vnf, arity, commute, knownNonNull, sharedStatic, extra) \ if (commute) \ - vnfOpAttribs[vnfNum] |= VNFOA_Commutative; \ + arr[vnfNum] |= VNFOA_Commutative; \ if (knownNonNull) \ - vnfOpAttribs[vnfNum] |= VNFOA_KnownNonNull; \ + arr[vnfNum] |= VNFOA_KnownNonNull; \ if (sharedStatic) \ - vnfOpAttribs[vnfNum] |= VNFOA_SharedStatic; \ + arr[vnfNum] |= VNFOA_SharedStatic; \ if (arity > 0) \ - vnfOpAttribs[vnfNum] |= ((arity << VNFOA_ArityShift) & VNFOA_ArityMask); \ + arr[vnfNum] |= ((arity << VNFOA_ArityShift) & VNFOA_ArityMask); \ vnfNum++; #include "valuenumfuncs.h" -#undef ValueNumFuncDef assert(vnfNum == VNF_COUNT); #define ValueNumFuncSetArity(vnfNum, arity) \ - vnfOpAttribs[vnfNum] &= ~VNFOA_ArityMask; /* clear old arity value */ \ - vnfOpAttribs[vnfNum] |= ((arity << VNFOA_ArityShift) & VNFOA_ArityMask) /* set the new arity value */ + arr[vnfNum] &= ~VNFOA_ArityMask; /* clear old arity value */ \ + arr[vnfNum] |= ((arity << VNFOA_ArityShift) & VNFOA_ArityMask) /* set the new arity value */ #ifdef FEATURE_HW_INTRINSICS @@ -8939,7 +8991,7 @@ void ValueNumStore::InitValueNumStoreStatics() // These HW_Intrinsic's have an extra VNF_SimdType arg. // VNFunc func = VNFunc(VNF_HWI_FIRST + (id - NI_HW_INTRINSIC_START - 1)); - unsigned oldArity = VNFuncArity(func); + unsigned oldArity = (arr[func] & VNFOA_ArityMask) >> VNFOA_ArityShift; unsigned newArity = oldArity + 1; ValueNumFuncSetArity(func, newArity); @@ -8948,7 +9000,7 @@ void ValueNumStore::InitValueNumStoreStatics() if (HWIntrinsicInfo::IsCommutative(id)) { VNFunc func = VNFunc(VNF_HWI_FIRST + (id - NI_HW_INTRINSIC_START - 1)); - vnfOpAttribs[func] |= VNFOA_Commutative; + arr[func] |= VNFOA_Commutative; } } @@ -8958,17 +9010,23 @@ void ValueNumStore::InitValueNumStoreStatics() for (unsigned i = 0; i < ArrLen(genTreeOpsIllegalAsVNFunc); i++) { - vnfOpAttribs[genTreeOpsIllegalAsVNFunc[i]] |= VNFOA_IllegalGenTreeOp; + arr[genTreeOpsIllegalAsVNFunc[i]] |= VNFOA_IllegalGenTreeOp; } + + assert(ArrLen(arr) == ArrLen(s_vnfOpAttribs)); + for (unsigned i = 0; i < ArrLen(arr); i++) + { + assert(arr[i] == s_vnfOpAttribs[i]); + } +#endif // DEBUG } #ifdef DEBUG // Define the name array. -#define ValueNumFuncDef(vnf, arity, commute, knownNonNull, sharedStatic) #vnf, +#define ValueNumFuncDef(vnf, arity, commute, knownNonNull, sharedStatic, extra) #vnf, const char* ValueNumStore::VNFuncNameArr[] = { #include "valuenumfuncs.h" -#undef ValueNumFuncDef }; /* static */ const char* ValueNumStore::VNFuncName(VNFunc vnf) @@ -11335,6 +11393,23 @@ void Compiler::fgValueNumberIntrinsic(GenTree* tree) else { assert(intrinsic->gtIntrinsicName == NI_System_Object_GetType); + + // Try to fold obj.GetType() if we know the exact type of obj. + bool isExact = false; + bool isNonNull = false; + CORINFO_CLASS_HANDLE cls = gtGetClassHandle(tree->gtGetOp1(), &isExact, &isNonNull); + if ((cls != NO_CLASS_HANDLE) && isExact && isNonNull) + { + CORINFO_OBJECT_HANDLE typeObj = info.compCompHnd->getRuntimeTypePointer(cls); + if (typeObj != nullptr) + { + setMethodHasFrozenObjects(); + ValueNum handleVN = vnStore->VNForHandle((ssize_t)typeObj, GTF_ICON_OBJ_HDL); + intrinsic->gtVNPair = vnStore->VNPWithExc(ValueNumPair(handleVN, handleVN), arg0VNPx); + return; + } + } + intrinsic->gtVNPair = vnStore->VNPWithExc(vnStore->VNPairForFunc(intrinsic->TypeGet(), VNF_ObjGetType, arg0VNP), arg0VNPx); } diff --git a/src/coreclr/jit/valuenum.h b/src/coreclr/jit/valuenum.h index 94ba28b9ab02b1..e63f4dad58fd4b 100644 --- a/src/coreclr/jit/valuenum.h +++ b/src/coreclr/jit/valuenum.h @@ -167,7 +167,7 @@ enum VNFunc { // Implicitly, elements of genTreeOps here. VNF_Boundary = GT_COUNT, -#define ValueNumFuncDef(nm, arity, commute, knownNonNull, sharedStatic) VNF_##nm, +#define ValueNumFuncDef(nm, arity, commute, knownNonNull, sharedStatic, extra) VNF_##nm, #include "valuenumfuncs.h" VNF_COUNT }; @@ -275,10 +275,21 @@ class ValueNumStore VNFOA_SharedStatic = 0x40, // 1 iff this VNF is represent one of the shared static jit helpers }; - static const unsigned VNFOA_ArityShift = 2; - static const unsigned VNFOA_ArityBits = 3; - static const unsigned VNFOA_MaxArity = (1 << VNFOA_ArityBits) - 1; // Max arity we can represent. - static const unsigned VNFOA_ArityMask = (VNFOA_Arity4 | VNFOA_Arity2 | VNFOA_Arity1); + static const unsigned VNFOA_IllegalGenTreeOpShift = 0; + static const unsigned VNFOA_CommutativeShift = 1; + static const unsigned VNFOA_ArityShift = 2; + static const unsigned VNFOA_ArityBits = 3; + static const unsigned VNFOA_MaxArity = (1 << VNFOA_ArityBits) - 1; // Max arity we can represent. + static const unsigned VNFOA_ArityMask = (VNFOA_Arity4 | VNFOA_Arity2 | VNFOA_Arity1); + static const unsigned VNFOA_KnownNonNullShift = 5; + static const unsigned VNFOA_SharedStaticShift = 6; + + static_assert(unsigned(VNFOA_IllegalGenTreeOp) == (1 << VNFOA_IllegalGenTreeOpShift)); + static_assert(unsigned(VNFOA_Commutative) == (1 << VNFOA_CommutativeShift)); + static_assert(unsigned(VNFOA_Arity1) == (1 << VNFOA_ArityShift)); + static_assert(VNFOA_ArityMask == (VNFOA_MaxArity << VNFOA_ArityShift)); + static_assert(unsigned(VNFOA_KnownNonNull) == (1 << VNFOA_KnownNonNullShift)); + static_assert(unsigned(VNFOA_SharedStatic) == (1 << VNFOA_SharedStaticShift)); // These enum constants are used to encode the cast operation in the lowest bits by VNForCastOper enum VNFCastAttrib @@ -289,8 +300,14 @@ class ValueNumStore VCA_ReservedBits = 0x01, // i.e. (VCA_UnsignedSrc) }; - // An array of length GT_COUNT, mapping genTreeOp values to their VNFOpAttrib. - static UINT8* s_vnfOpAttribs; + // Helpers and an array of length GT_COUNT, mapping genTreeOp values to their VNFOpAttrib. + static constexpr uint8_t GetOpAttribsForArity(genTreeOps oper, GenTreeOperKind kind); + static constexpr uint8_t GetOpAttribsForGenTree(genTreeOps oper, + bool commute, + bool illegalAsVNFunc, + GenTreeOperKind kind); + static constexpr uint8_t GetOpAttribsForFunc(int arity, bool commute, bool knownNonNull, bool sharedStatic); + static const uint8_t s_vnfOpAttribs[]; // Returns "true" iff gtOper is a legal value number function. // (Requires InitValueNumStoreStatics to have been run.) @@ -383,8 +400,8 @@ class ValueNumStore GenTreeFlags GetFoldedArithOpResultHandleFlags(ValueNum vn); public: - // Initializes any static variables of ValueNumStore. - static void InitValueNumStoreStatics(); + // Validate that the new initializer for s_vnfOpAttribs matches the old code. + static void ValidateValueNumStoreStatics(); // Initialize an empty ValueNumStore. ValueNumStore(Compiler* comp, CompAllocator allocator); diff --git a/src/coreclr/jit/valuenumfuncs.h b/src/coreclr/jit/valuenumfuncs.h index 1c6c72bb87fa06..de0c347591a8d2 100644 --- a/src/coreclr/jit/valuenumfuncs.h +++ b/src/coreclr/jit/valuenumfuncs.h @@ -3,180 +3,180 @@ // Defines the functions understood by the value-numbering system. // ValueNumFuncDef(, , , , -// ) +// , ) // clang-format off -ValueNumFuncDef(MemOpaque, 1, false, false, false) // Args: 0: loop num -ValueNumFuncDef(MapSelect, 2, false, false, false) // Args: 0: map, 1: key. -ValueNumFuncDef(MapStore, 4, false, false, false) // Args: 0: map, 1: index (e. g. field handle), 2: value being stored, 3: loop num. -ValueNumFuncDef(MapPhysicalStore, 3, false, false, false) // Args: 0: map, 1: "physical selector": offset and size, 2: value being stored -ValueNumFuncDef(BitCast, 2, false, false, false) // Args: 0: VN of the arg, 1: VN of the target type -ValueNumFuncDef(ZeroObj, 1, false, false, false) // Args: 0: VN of the class handle. -ValueNumFuncDef(PhiDef, 3, false, false, false) // Args: 0: local var # (or -1 for memory), 1: SSA #, 2: VN of definition. -ValueNumFuncDef(PhiMemoryDef, 2, false, false, false) // Args: 0: VN for basic block pointer, 1: VN of definition -ValueNumFuncDef(Phi, 2, false, false, false) // A phi function. Only occurs as arg of PhiDef or PhiMemoryDef. Arguments are SSA numbers of var being defined. - -ValueNumFuncDef(PtrToLoc, 2, false, true, false) // Pointer (byref) to a local variable. Args: VN's of: 0: local's number, 1: offset. -ValueNumFuncDef(PtrToArrElem, 4, false, false, false) // Pointer (byref) to an array element. Args: 0: array elem type eq class var_types value, VN's of: 1: array, 2: index, 3: offset. -ValueNumFuncDef(PtrToStatic, 3, false, true, false) // Pointer (byref) to a static variable (or possibly a field thereof, if the static variable is a struct). - // Args: 0: (VN of) the box's address if the static is "boxed", - // 1: (VN of) the field sequence, - // 2: (VN of) offset for the constituent struct fields - -ValueNumFuncDef(MDArrLength, 2, false, false, false) // MD array len, Args: 0: array, 1: dimension -ValueNumFuncDef(MDArrLowerBound, 2, false, false, false) // MD array lower bound, Args: 0: array, 1: dimension - -ValueNumFuncDef(InitVal, 1, false, false, false) // An input arg, or init val of a local Args: 0: a constant VN. - -ValueNumFuncDef(Cast, 2, false, false, false) // VNF_Cast: Cast Operation changes the representations size and unsigned-ness. - // Args: 0: Source for the cast operation. - // 1: Constant integer representing the operation . - // Use VNForCastOper() to construct. -ValueNumFuncDef(CastOvf, 2, false, false, false) // Same as a VNF_Cast but also can throw an overflow exception. - -ValueNumFuncDef(CastClass, 2, false, false, false) // Args: 0: Handle of class being cast to, 1: object being cast. -ValueNumFuncDef(IsInstanceOf, 2, false, false, false) // Args: 0: Handle of class being queried, 1: object being queried. -ValueNumFuncDef(ReadyToRunCastClass, 2, false, false, false) // Args: 0: Helper stub address, 1: object being cast. -ValueNumFuncDef(ReadyToRunIsInstanceOf, 2, false, false, false) // Args: 0: Helper stub address, 1: object being queried. -ValueNumFuncDef(TypeHandleToRuntimeType, 1, false, false, false) // Args: 0: TypeHandle to translate -ValueNumFuncDef(TypeHandleToRuntimeTypeHandle, 1, false, false, false) // Args: 0: TypeHandle to translate - -ValueNumFuncDef(LdElemA, 3, false, false, false) // Args: 0: array value; 1: index value; 2: type handle of element. - -ValueNumFuncDef(ByrefExposedLoad, 3, false, false, false) // Args: 0: type handle/id, 1: pointer value; 2: ByrefExposed heap value - -ValueNumFuncDef(GetRefanyVal, 2, false, false, false) // Args: 0: type handle; 1: typedref value. Returns the value (asserting that the type is right). - -ValueNumFuncDef(GetClassFromMethodParam, 1, false, true, false) // Args: 0: method generic argument. -ValueNumFuncDef(GetSyncFromClassHandle, 1, false, true, false) // Args: 0: class handle. -ValueNumFuncDef(LoopCloneChoiceAddr, 0, false, true, false) +ValueNumFuncDef(MemOpaque, 1, false, false, false, false) // Args: 0: loop num +ValueNumFuncDef(MapSelect, 2, false, false, false, false) // Args: 0: map, 1: key. +ValueNumFuncDef(MapStore, 4, false, false, false, false) // Args: 0: map, 1: index (e. g. field handle), 2: value being stored, 3: loop num. +ValueNumFuncDef(MapPhysicalStore, 3, false, false, false, false) // Args: 0: map, 1: "physical selector": offset and size, 2: value being stored +ValueNumFuncDef(BitCast, 2, false, false, false, false) // Args: 0: VN of the arg, 1: VN of the target type +ValueNumFuncDef(ZeroObj, 1, false, false, false, false) // Args: 0: VN of the class handle. +ValueNumFuncDef(PhiDef, 3, false, false, false, false) // Args: 0: local var # (or -1 for memory), 1: SSA #, 2: VN of definition. +ValueNumFuncDef(PhiMemoryDef, 2, false, false, false, false) // Args: 0: VN for basic block pointer, 1: VN of definition +ValueNumFuncDef(Phi, 2, false, false, false, false) // A phi function. Only occurs as arg of PhiDef or PhiMemoryDef. Arguments are SSA numbers of var being defined. + +ValueNumFuncDef(PtrToLoc, 2, false, true, false, false) // Pointer (byref) to a local variable. Args: VN's of: 0: local's number, 1: offset. +ValueNumFuncDef(PtrToArrElem, 4, false, false, false, false) // Pointer (byref) to an array element. Args: 0: array elem type eq class var_types value, VN's of: 1: array, 2: index, 3: offset. +ValueNumFuncDef(PtrToStatic, 3, false, true, false, false) // Pointer (byref) to a static variable (or possibly a field thereof, if the static variable is a struct). + // Args: 0: (VN of) the box's address if the static is "boxed", + // 1: (VN of) the field sequence, + // 2: (VN of) offset for the constituent struct fields + +ValueNumFuncDef(MDArrLength, 2, false, false, false, false) // MD array len, Args: 0: array, 1: dimension +ValueNumFuncDef(MDArrLowerBound, 2, false, false, false, false) // MD array lower bound, Args: 0: array, 1: dimension + +ValueNumFuncDef(InitVal, 1, false, false, false, false) // An input arg, or init val of a local Args: 0: a constant VN. + +ValueNumFuncDef(Cast, 2, false, false, false, false) // VNF_Cast: Cast Operation changes the representations size and unsigned-ness. + // Args: 0: Source for the cast operation. + // 1: Constant integer representing the operation . + // Use VNForCastOper() to construct. +ValueNumFuncDef(CastOvf, 2, false, false, false, false) // Same as a VNF_Cast but also can throw an overflow exception. + +ValueNumFuncDef(CastClass, 2, false, false, false, false) // Args: 0: Handle of class being cast to, 1: object being cast. +ValueNumFuncDef(IsInstanceOf, 2, false, false, false, false) // Args: 0: Handle of class being queried, 1: object being queried. +ValueNumFuncDef(ReadyToRunCastClass, 2, false, false, false, false) // Args: 0: Helper stub address, 1: object being cast. +ValueNumFuncDef(ReadyToRunIsInstanceOf, 2, false, false, false, false) // Args: 0: Helper stub address, 1: object being queried. +ValueNumFuncDef(TypeHandleToRuntimeType, 1, false, false, false, false) // Args: 0: TypeHandle to translate +ValueNumFuncDef(TypeHandleToRuntimeTypeHandle, 1, false, false, false, false) // Args: 0: TypeHandle to translate + +ValueNumFuncDef(LdElemA, 3, false, false, false, false) // Args: 0: array value; 1: index value; 2: type handle of element. + +ValueNumFuncDef(ByrefExposedLoad, 3, false, false, false, false) // Args: 0: type handle/id, 1: pointer value; 2: ByrefExposed heap value + +ValueNumFuncDef(GetRefanyVal, 2, false, false, false, false) // Args: 0: type handle; 1: typedref value. Returns the value (asserting that the type is right). + +ValueNumFuncDef(GetClassFromMethodParam, 1, false, true, false, false) // Args: 0: method generic argument. +ValueNumFuncDef(GetSyncFromClassHandle, 1, false, true, false, false) // Args: 0: class handle. +ValueNumFuncDef(LoopCloneChoiceAddr, 0, false, true, false, false) // How we represent values of expressions with exceptional side effects: -ValueNumFuncDef(ValWithExc, 2, false, false, false) // Args: 0: value number from normal execution; 1: VN for set of possible exceptions. -ValueNumFuncDef(ExcSetCons, 2, false, false, false) // Args: 0: exception; 1: exception set (including EmptyExcSet). Invariant: "car"s are always in ascending order. +ValueNumFuncDef(ValWithExc, 2, false, false, false, false) // Args: 0: value number from normal execution; 1: VN for set of possible exceptions. +ValueNumFuncDef(ExcSetCons, 2, false, false, false, false) // Args: 0: exception; 1: exception set (including EmptyExcSet). Invariant: "car"s are always in ascending order. // Various functions that are used to indicate that an exceptions may occur // Curremtly when the execution is always thrown, the value VNForVoid() is used as Arg0 by OverflowExc and DivideByZeroExc // -ValueNumFuncDef(NullPtrExc, 1, false, false, false) // Null pointer exception check. Args: 0: address value, throws when it is null -ValueNumFuncDef(ArithmeticExc, 2, false, false, false) // Arithmetic exception check, ckfinite and integer division overflow, Args: 0: expression value, -ValueNumFuncDef(OverflowExc, 1, false, false, false) // Integer overflow check. used for checked add,sub and mul Args: 0: expression value, throws when it overflows -ValueNumFuncDef(ConvOverflowExc, 2, false, false, false) // Cast conversion overflow check. Args: 0: input value; 1: var_types of the target type +ValueNumFuncDef(NullPtrExc, 1, false, false, false, false) // Null pointer exception check. Args: 0: address value, throws when it is null +ValueNumFuncDef(ArithmeticExc, 2, false, false, false, false) // Arithmetic exception check, ckfinite and integer division overflow, Args: 0: expression value, +ValueNumFuncDef(OverflowExc, 1, false, false, false, false) // Integer overflow check. used for checked add,sub and mul Args: 0: expression value, throws when it overflows +ValueNumFuncDef(ConvOverflowExc, 2, false, false, false, false) // Cast conversion overflow check. Args: 0: input value; 1: var_types of the target type // - (shifted left one bit; low bit encode whether source is unsigned.) -ValueNumFuncDef(DivideByZeroExc, 1, false, false, false) // Division by zero check. Args: 0: divisor value, throws when it is zero -ValueNumFuncDef(IndexOutOfRangeExc, 2, 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) // CastClass check, Args: 0: ref value being cast; 1: handle of type being cast to, throws when the cast fails. -ValueNumFuncDef(NewArrOverflowExc, 1, false, false, false) // Raises Integer overflow when Arg 0 is negative -ValueNumFuncDef(HelperMultipleExc, 0, false, false, false) // Represents one or more different exceptions that could be thrown by a Jit Helper method - -ValueNumFuncDef(FltRound, 1, false, false, false) -ValueNumFuncDef(DblRound, 1, false, false, false) - -ValueNumFuncDef(Abs, 1, false, false, false) -ValueNumFuncDef(Acos, 1, false, false, false) -ValueNumFuncDef(Acosh, 1, false, false, false) -ValueNumFuncDef(Asin, 1, false, false, false) -ValueNumFuncDef(Asinh, 1, false, false, false) -ValueNumFuncDef(Atan, 1, false, false, false) -ValueNumFuncDef(Atanh, 1, false, false, false) -ValueNumFuncDef(Atan2, 2, false, false, false) -ValueNumFuncDef(Cbrt, 1, false, false, false) -ValueNumFuncDef(Ceiling, 1, false, false, false) -ValueNumFuncDef(Cos, 1, false, false, false) -ValueNumFuncDef(Cosh, 1, false, false, false) -ValueNumFuncDef(Exp, 1, false, false, false) -ValueNumFuncDef(Floor, 1, false, false, false) -ValueNumFuncDef(FMod, 2, false, false, false) -ValueNumFuncDef(ILogB, 1, false, false, false) -ValueNumFuncDef(Log, 1, false, false, false) -ValueNumFuncDef(Log2, 1, false, false, false) -ValueNumFuncDef(Log10, 1, false, false, false) -ValueNumFuncDef(Max, 2, false, false, false) -ValueNumFuncDef(Min, 2, false, false, false) -ValueNumFuncDef(Pow, 2, false, false, false) -ValueNumFuncDef(RoundDouble, 1, false, false, false) -ValueNumFuncDef(RoundInt32, 1, false, false, false) -ValueNumFuncDef(RoundSingle, 1, false, false, false) -ValueNumFuncDef(Sin, 1, false, false, false) -ValueNumFuncDef(Sinh, 1, false, false, false) -ValueNumFuncDef(Sqrt, 1, false, false, false) -ValueNumFuncDef(Tan, 1, false, false, false) -ValueNumFuncDef(Tanh, 1, false, false, false) -ValueNumFuncDef(Truncate, 1, false, false, false) - -ValueNumFuncDef(ManagedThreadId, 0, false, false, false) - -ValueNumFuncDef(ObjGetType, 1, false, true, false) -ValueNumFuncDef(GetgenericsGcstaticBase, 1, false, true, true) -ValueNumFuncDef(GetgenericsNongcstaticBase, 1, false, true, true) -ValueNumFuncDef(GetsharedGcstaticBase, 2, false, true, true) -ValueNumFuncDef(GetsharedNongcstaticBase, 2, false, true, true) -ValueNumFuncDef(GetsharedGcstaticBaseNoctor, 1, false, true, true) -ValueNumFuncDef(GetsharedNongcstaticBaseNoctor, 1, false, true, true) -ValueNumFuncDef(ReadyToRunStaticBaseGC, 1, false, true, true) -ValueNumFuncDef(ReadyToRunStaticBaseNonGC, 1, false, true, true) -ValueNumFuncDef(ReadyToRunStaticBaseThread, 1, false, true, true) -ValueNumFuncDef(ReadyToRunStaticBaseThreadNonGC, 1, false, true, true) -ValueNumFuncDef(ReadyToRunGenericStaticBase, 2, false, true, true) -ValueNumFuncDef(GetsharedGcstaticBaseDynamicclass, 2, false, true, true) -ValueNumFuncDef(GetsharedNongcstaticBaseDynamicclass, 2, false, true, true) -ValueNumFuncDef(GetgenericsGcthreadstaticBase, 1, false, true, true) -ValueNumFuncDef(GetgenericsNongcthreadstaticBase, 1, false, true, true) -ValueNumFuncDef(GetsharedGcthreadstaticBase, 2, false, true, true) -ValueNumFuncDef(GetsharedNongcthreadstaticBase, 2, false, true, true) -ValueNumFuncDef(GetsharedGcthreadstaticBaseNoctor, 2, false, true, true) -ValueNumFuncDef(GetsharedGcthreadstaticBaseNoctorOptimized, 1, false, true, true) -ValueNumFuncDef(GetsharedNongcthreadstaticBaseNoctor, 2, false, true, true) -ValueNumFuncDef(GetsharedNongcthreadstaticBaseNoctorOptimized, 1, false, true, true) -ValueNumFuncDef(GetsharedGcthreadstaticBaseDynamicclass, 2, false, true, true) -ValueNumFuncDef(GetsharedNongcthreadstaticBaseDynamicclass, 2, false, true, true) - -ValueNumFuncDef(ClassinitSharedDynamicclass, 2, false, false, false) -ValueNumFuncDef(RuntimeHandleMethod, 2, false, true, false) -ValueNumFuncDef(RuntimeHandleClass, 2, false, true, false) -ValueNumFuncDef(ReadyToRunGenericHandle, 2, false, true, false) - -ValueNumFuncDef(GetStaticAddrTLS, 1, false, true, false) - -ValueNumFuncDef(JitNew, 2, false, true, false) -ValueNumFuncDef(JitNewArr, 3, false, true, false) -ValueNumFuncDef(JitNewMdArr, 4, false, true, false) -ValueNumFuncDef(JitReadyToRunNew, 2, false, true, false) -ValueNumFuncDef(JitReadyToRunNewArr, 3, false, true, false) -ValueNumFuncDef(Box, 3, false, false, false) -ValueNumFuncDef(BoxNullable, 3, false, false, false) - -ValueNumFuncDef(LazyStrCns, 2, false, true, false) // Lazy-initialized string literal (helper) -ValueNumFuncDef(InvariantLoad, 1, false, false, false) // Args: 0: (VN of) the address. -ValueNumFuncDef(InvariantNonNullLoad, 1, false, true, false) // Args: 0: (VN of) the address. -ValueNumFuncDef(Unbox, 2, false, true, false) - -ValueNumFuncDef(LT_UN, 2, false, false, false) // unsigned or unordered comparisons -ValueNumFuncDef(LE_UN, 2, false, false, false) -ValueNumFuncDef(GE_UN, 2, false, false, false) -ValueNumFuncDef(GT_UN, 2, false, false, false) - -ValueNumFuncDef(ADD_OVF, 2, true, false, false) // overflow checking operations -ValueNumFuncDef(SUB_OVF, 2, false, false, false) -ValueNumFuncDef(MUL_OVF, 2, true, false, false) - -ValueNumFuncDef(ADD_UN_OVF, 2, true, false, false) // unsigned overflow checking operations -ValueNumFuncDef(SUB_UN_OVF, 2, false, false, false) -ValueNumFuncDef(MUL_UN_OVF, 2, true, false, false) +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(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(FltRound, 1, false, false, false, false) +ValueNumFuncDef(DblRound, 1, false, false, false, false) + +ValueNumFuncDef(Abs, 1, false, false, false, false) +ValueNumFuncDef(Acos, 1, false, false, false, false) +ValueNumFuncDef(Acosh, 1, false, false, false, false) +ValueNumFuncDef(Asin, 1, false, false, false, false) +ValueNumFuncDef(Asinh, 1, false, false, false, false) +ValueNumFuncDef(Atan, 1, false, false, false, false) +ValueNumFuncDef(Atanh, 1, false, false, false, false) +ValueNumFuncDef(Atan2, 2, false, false, false, false) +ValueNumFuncDef(Cbrt, 1, false, false, false, false) +ValueNumFuncDef(Ceiling, 1, false, false, false, false) +ValueNumFuncDef(Cos, 1, false, false, false, false) +ValueNumFuncDef(Cosh, 1, false, false, false, false) +ValueNumFuncDef(Exp, 1, false, false, false, false) +ValueNumFuncDef(Floor, 1, false, false, false, false) +ValueNumFuncDef(FMod, 2, false, false, false, false) +ValueNumFuncDef(ILogB, 1, false, false, false, false) +ValueNumFuncDef(Log, 1, false, false, false, false) +ValueNumFuncDef(Log2, 1, false, false, false, false) +ValueNumFuncDef(Log10, 1, false, false, false, false) +ValueNumFuncDef(Max, 2, false, false, false, false) +ValueNumFuncDef(Min, 2, false, false, false, false) +ValueNumFuncDef(Pow, 2, false, false, false, false) +ValueNumFuncDef(RoundDouble, 1, false, false, false, false) +ValueNumFuncDef(RoundInt32, 1, false, false, false, false) +ValueNumFuncDef(RoundSingle, 1, false, false, false, false) +ValueNumFuncDef(Sin, 1, false, false, false, false) +ValueNumFuncDef(Sinh, 1, false, false, false, false) +ValueNumFuncDef(Sqrt, 1, false, false, false, false) +ValueNumFuncDef(Tan, 1, false, false, false, false) +ValueNumFuncDef(Tanh, 1, false, false, false, false) +ValueNumFuncDef(Truncate, 1, false, false, false, false) + +ValueNumFuncDef(ManagedThreadId, 0, false, false, false, false) + +ValueNumFuncDef(ObjGetType, 1, false, true, false, false) +ValueNumFuncDef(GetgenericsGcstaticBase, 1, false, true, true, false) +ValueNumFuncDef(GetgenericsNongcstaticBase, 1, false, true, true, false) +ValueNumFuncDef(GetsharedGcstaticBase, 2, false, true, true, false) +ValueNumFuncDef(GetsharedNongcstaticBase, 2, false, true, true, false) +ValueNumFuncDef(GetsharedGcstaticBaseNoctor, 1, false, true, true, false) +ValueNumFuncDef(GetsharedNongcstaticBaseNoctor, 1, false, true, true, false) +ValueNumFuncDef(ReadyToRunStaticBaseGC, 1, false, true, true, false) +ValueNumFuncDef(ReadyToRunStaticBaseNonGC, 1, false, true, true, false) +ValueNumFuncDef(ReadyToRunStaticBaseThread, 1, false, true, true, false) +ValueNumFuncDef(ReadyToRunStaticBaseThreadNonGC, 1, false, true, true, false) +ValueNumFuncDef(ReadyToRunGenericStaticBase, 2, false, true, true, false) +ValueNumFuncDef(GetsharedGcstaticBaseDynamicclass, 2, false, true, true, false) +ValueNumFuncDef(GetsharedNongcstaticBaseDynamicclass, 2, false, true, true, false) +ValueNumFuncDef(GetgenericsGcthreadstaticBase, 1, false, true, true, false) +ValueNumFuncDef(GetgenericsNongcthreadstaticBase, 1, false, true, true, false) +ValueNumFuncDef(GetsharedGcthreadstaticBase, 2, false, true, true, false) +ValueNumFuncDef(GetsharedNongcthreadstaticBase, 2, false, true, true, false) +ValueNumFuncDef(GetsharedGcthreadstaticBaseNoctor, 2, false, true, true, false) +ValueNumFuncDef(GetsharedGcthreadstaticBaseNoctorOptimized, 1, false, true, true, false) +ValueNumFuncDef(GetsharedNongcthreadstaticBaseNoctor, 2, false, true, true, false) +ValueNumFuncDef(GetsharedNongcthreadstaticBaseNoctorOptimized, 1, false, true, true, false) +ValueNumFuncDef(GetsharedGcthreadstaticBaseDynamicclass, 2, false, true, true, false) +ValueNumFuncDef(GetsharedNongcthreadstaticBaseDynamicclass, 2, false, true, true, false) + +ValueNumFuncDef(ClassinitSharedDynamicclass, 2, false, false, false, false) +ValueNumFuncDef(RuntimeHandleMethod, 2, false, true, false, false) +ValueNumFuncDef(RuntimeHandleClass, 2, false, true, false, false) +ValueNumFuncDef(ReadyToRunGenericHandle, 2, false, true, false, false) + +ValueNumFuncDef(GetStaticAddrTLS, 1, false, true, false, false) + +ValueNumFuncDef(JitNew, 2, false, true, false, false) +ValueNumFuncDef(JitNewArr, 3, false, true, false, false) +ValueNumFuncDef(JitNewMdArr, 4, false, true, false, false) +ValueNumFuncDef(JitReadyToRunNew, 2, false, true, false, false) +ValueNumFuncDef(JitReadyToRunNewArr, 3, false, true, false, false) +ValueNumFuncDef(Box, 3, false, false, false, false) +ValueNumFuncDef(BoxNullable, 3, false, false, false, false) + +ValueNumFuncDef(LazyStrCns, 2, false, true, false, false) // Lazy-initialized string literal (helper) +ValueNumFuncDef(InvariantLoad, 1, false, false, false, false) // Args: 0: (VN of) the address. +ValueNumFuncDef(InvariantNonNullLoad, 1, false, true, false, false) // Args: 0: (VN of) the address. +ValueNumFuncDef(Unbox, 2, false, true, false, false) + +ValueNumFuncDef(LT_UN, 2, false, false, false, false) // unsigned or unordered comparisons +ValueNumFuncDef(LE_UN, 2, false, false, false, false) +ValueNumFuncDef(GE_UN, 2, false, false, false, false) +ValueNumFuncDef(GT_UN, 2, false, false, false, false) + +ValueNumFuncDef(ADD_OVF, 2, true, false, false, false) // overflow checking operations +ValueNumFuncDef(SUB_OVF, 2, false, false, false, false) +ValueNumFuncDef(MUL_OVF, 2, true, false, false, false) + +ValueNumFuncDef(ADD_UN_OVF, 2, true, false, false, false) // unsigned overflow checking operations +ValueNumFuncDef(SUB_UN_OVF, 2, false, false, false, false) +ValueNumFuncDef(MUL_UN_OVF, 2, true, false, false, false) #ifdef FEATURE_SIMD -ValueNumFuncDef(SimdType, 2, false, false, false) // A value number function to compose a SIMD type +ValueNumFuncDef(SimdType, 2, false, false, false, false) // A value number function to compose a SIMD type #endif #if defined(TARGET_XARCH) -#define HARDWARE_INTRINSIC(isa, name, size, argCount, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \ -ValueNumFuncDef(HWI_##isa##_##name, argCount, false, false, false) // All of the HARDWARE_INTRINSICS for x86/x64 +#define HARDWARE_INTRINSIC(isa, name, size, argCount, extra, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \ +ValueNumFuncDef(HWI_##isa##_##name, argCount, ((flag) & HW_Flag_Commutative) >> 0, false, false, extra) // All of the HARDWARE_INTRINSICS for x86/x64 #include "hwintrinsiclistxarch.h" #define VNF_HWI_FIRST VNF_HWI_Vector128_Abs #elif defined (TARGET_ARM64) -#define HARDWARE_INTRINSIC(isa, name, size, argCount, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \ -ValueNumFuncDef(HWI_##isa##_##name, argCount, false, false, false) // All of the HARDWARE_INTRINSICS for arm64 +#define HARDWARE_INTRINSIC(isa, name, size, argCount, extra, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, category, flag) \ +ValueNumFuncDef(HWI_##isa##_##name, argCount, ((flag) & HW_Flag_Commutative) >> 0, false, false, extra) // All of the HARDWARE_INTRINSICS for arm64 #include "hwintrinsiclistarm64.h" #define VNF_HWI_FIRST VNF_HWI_Vector64_Abs diff --git a/src/coreclr/md/ceefilegen/cceegen.cpp b/src/coreclr/md/ceefilegen/cceegen.cpp index 050d16288ef93b..391411b3984aec 100644 --- a/src/coreclr/md/ceefilegen/cceegen.cpp +++ b/src/coreclr/md/ceefilegen/cceegen.cpp @@ -178,20 +178,6 @@ STDMETHODIMP CCeeGen::ComputePointer(HCEESECTION section, ULONG RVA, UCHAR **lpB return hr; } -STDMETHODIMP CCeeGen::GetIMapTokenIface ( - IUnknown **pIMapToken) -{ - _ASSERTE(!"E_NOTIMPL"); - return E_NOTIMPL; -} - -STDMETHODIMP CCeeGen::AddNotificationHandler ( - IUnknown *pHandler) -{ - _ASSERTE(!"E_NOTIMPL"); - return E_NOTIMPL; -} - STDMETHODIMP CCeeGen::GenerateCeeFile () { _ASSERTE(!"E_NOTIMPL"); @@ -260,8 +246,6 @@ CCeeGen::CCeeGen() // protected ctor m_cRefs = 0; m_peSectionMan = NULL; m_pTokenMap = NULL; - m_pRemapHandler = NULL; - } // Shared init code between derived classes, called by virtual Init() @@ -288,7 +272,6 @@ HRESULT CCeeGen::Init() // not-virtual, protected m_pTokenMap = NULL; m_fTokenMapSupported = FALSE; - m_pRemapHandler = NULL; // These text section needs special support for handling string management now that we have // merged the sections together, so create it with an underlying CeeSectionString rather than the @@ -321,17 +304,6 @@ HRESULT CCeeGen::Init() // not-virtual, protected return hr; } -HRESULT CCeeGen::cloneInstance(CCeeGen *destination) { //public, virtual - _ASSERTE(destination); - - destination->m_pTokenMap = m_pTokenMap; - destination->m_fTokenMapSupported = m_fTokenMapSupported; - destination->m_pRemapHandler = m_pRemapHandler; - - //Create a deep copy of the section manager (and each of it's sections); - return m_peSectionMan->cloneInstance(destination->m_peSectionMan); -} - HRESULT CCeeGen::Cleanup() // virtual { HRESULT hr; @@ -357,12 +329,6 @@ HRESULT CCeeGen::Cleanup() // virtual m_pTokenMap = NULL; } - if (m_pRemapHandler) - { - m_pRemapHandler->Release(); - m_pRemapHandler = NULL; - } - if (m_peSectionMan) { m_peSectionMan->Cleanup(); delete m_peSectionMan; @@ -546,48 +512,7 @@ HRESULT CCeeGen::getMapTokenIface(IUnknown **pIMapToken, IMetaDataEmit *emitter) } m_pTokenMap = pMapper; m_fTokenMapSupported = (emitter == 0); - - // If we've been holding onto a token remap handler waiting - // for the token mapper to get created, add it to the token - // mapper now and release our hold on it. - if (m_pRemapHandler && m_pTokenMap) - { - m_pTokenMap->AddTokenMapper(m_pRemapHandler); - m_pRemapHandler->Release(); - m_pRemapHandler = NULL; - } } *pIMapToken = getTokenMapper()->GetMapTokenIface(); return S_OK; } - -HRESULT CCeeGen::addNotificationHandler(IUnknown *pHandler) -{ - // Null is no good... - if (!pHandler) - return E_POINTER; - - HRESULT hr = S_OK; - IMapToken *pIMapToken = NULL; - - // Is this an IMapToken? If so, we can put it to good use... - if (SUCCEEDED(pHandler->QueryInterface(IID_IMapToken, - (void**)&pIMapToken))) - { - // You gotta have a token mapper to use an IMapToken, though. - if (m_pTokenMap) - { - hr = m_pTokenMap->AddTokenMapper(pIMapToken); - pIMapToken->Release(); - } - else - { - // Hold onto it for later, just in case a token mapper - // gets created. We're holding a reference to it here, - // too. - m_pRemapHandler = pIMapToken; - } - } - - return hr; -} diff --git a/src/coreclr/md/ceefilegen/ceegentokenmapper.cpp b/src/coreclr/md/ceefilegen/ceegentokenmapper.cpp index bf4118948c5084..fe9bc3f7c08b0b 100644 --- a/src/coreclr/md/ceefilegen/ceegentokenmapper.cpp +++ b/src/coreclr/md/ceefilegen/ceegentokenmapper.cpp @@ -58,11 +58,6 @@ HRESULT STDMETHODCALLTYPE CeeGenTokenMapper::Map( _ASSERTE(IndexForType(tkFrom) < GetMaxMapSize()); _ASSERTE(IndexForType(tkTo) != -1 && IndexForType(tkTo) < GetMaxMapSize()); - // If there is another token mapper that the user wants called, go - // ahead and call it now. - if (m_pIMapToken) - m_pIMapToken->Map(tkFrom, tkTo); - ridFrom = RidFromToken(tkFrom); pMap = &m_rgMap[IndexForType(tkFrom)]; diff --git a/src/coreclr/md/ceefilegen/pesectionman.cpp b/src/coreclr/md/ceefilegen/pesectionman.cpp index 42635acc6c7154..cee08e25a77313 100644 --- a/src/coreclr/md/ceefilegen/pesectionman.cpp +++ b/src/coreclr/md/ceefilegen/pesectionman.cpp @@ -148,44 +148,6 @@ HRESULT PESectionMan::newSection(const char* name, PESection **section, return S_OK; } -//Clone each of our sections. This will cause a deep copy of the sections -HRESULT PESectionMan::cloneInstance(PESectionMan *destination) { - _ASSERTE(destination); - PESection *pSection; - PESection **destPtr; - HRESULT hr = NOERROR; - - //Copy each of the sections - for (PESection** ptr = sectStart; ptr < sectCur; ptr++) { - destPtr = destination->sectStart; - pSection = NULL; - - // try to find the matching section by name - for (; destPtr < destination->sectCur; destPtr++) - { - if (strcmp((*destPtr)->m_name, (*ptr)->m_name) == 0) - { - pSection = *destPtr; - break; - } - } - if (destPtr >= destination->sectCur) - { - // cannot find a section in the destination with matching name - // so create one! - IfFailRet( destination->getSectionCreate((*ptr)->m_name, - (*ptr)->flags(), - &pSection) ); - } - if (pSection) - IfFailRet( (*ptr)->cloneInstance(pSection) ); - } - - //destination->sectEnd=destination->sectStart + (sectEnd-sectStart); - return S_OK; -} - - //***************************************************************************** // Implementation for PESection //***************************************************************************** @@ -380,47 +342,6 @@ HRESULT PESection::applyRelocs(CeeGenTokenMapper *pTokenMapper) return S_OK; } -HRESULT PESection::cloneInstance(PESection *destination) { - PESectionReloc *cur; - INT32 newSize; - HRESULT hr = NOERROR; - - _ASSERTE(destination); - - destination->dirEntry = dirEntry; - - //Merge the information currently in the BlobFetcher into - //out current blob fetcher - m_blobFetcher.Merge(&(destination->m_blobFetcher)); - - //Copy the name. - strncpy_s(destination->m_name, sizeof(destination->m_name), m_name, sizeof(m_name) - 1); - - //Clone the relocs - //If the arrays aren't the same size, reallocate as necessary. - //@FUTURE: Make this a ref-counted structure and don't copy it. - - newSize = (INT32)(m_relocCur-m_relocStart); - - if (newSize>(destination->m_relocEnd - destination->m_relocStart)) { - delete[] destination->m_relocStart; - - destination->m_relocStart = new (nothrow) PESectionReloc[newSize]; - if (destination->m_relocStart == NULL) - IfFailGo( E_OUTOFMEMORY ); - destination->m_relocEnd = destination->m_relocStart+(newSize); - } - - //copy the correct data over into our new array. - memcpy(destination->m_relocStart, m_relocStart, sizeof(PESectionReloc)*(newSize)); - destination->m_relocCur = destination->m_relocStart + (newSize); - for (cur=destination->m_relocStart; curm_relocCur; cur++) { - cur->section=destination; - } -ErrExit: - return hr; -} - void PESection::SetInitialGrowth(unsigned growth) { m_blobFetcher.SetInitialGrowth(growth); diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets index ad2c022f4be7fc..2412bd4b7947a4 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.Unix.targets @@ -48,7 +48,7 @@ The .NET Foundation licenses this file to you under the MIT license. @executable_path libeventpipe-disabled - libeventpipe-enabled + libeventpipe-enabled @@ -96,7 +96,7 @@ The .NET Foundation licenses this file to you under the MIT license. - + @@ -119,12 +119,12 @@ The .NET Foundation licenses this file to you under the MIT license. - - + + - + diff --git a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets index 9ce8ef00756dd6..e11fac5806808d 100644 --- a/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets +++ b/src/coreclr/nativeaot/BuildIntegration/Microsoft.NETCore.Native.targets @@ -214,12 +214,11 @@ The .NET Foundation licenses this file to you under the MIT license. - - + @@ -230,6 +229,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 76c5cb9eecbb72..dce8e37c32fe38 100644 --- a/src/coreclr/nativeaot/Directory.Build.props +++ b/src/coreclr/nativeaot/Directory.Build.props @@ -65,8 +65,7 @@ FEATURE_OBJCMARSHAL;$(DefineConstants) - false - true + true FEATURE_PERFTRACING;$(DefineConstants) diff --git a/src/coreclr/nativeaot/Runtime.Base/src/System/RuntimeTypeHandle.cs b/src/coreclr/nativeaot/Runtime.Base/src/System/RuntimeTypeHandle.cs index 85f880035e904b..8ecb99bc49e584 100644 --- a/src/coreclr/nativeaot/Runtime.Base/src/System/RuntimeTypeHandle.cs +++ b/src/coreclr/nativeaot/Runtime.Base/src/System/RuntimeTypeHandle.cs @@ -18,6 +18,6 @@ public class Type [StructLayout(LayoutKind.Sequential)] public struct RuntimeTypeHandle { - private EETypePtr _pEEType; + private IntPtr _value; } } diff --git a/src/coreclr/nativeaot/Runtime/AsmOffsets.h b/src/coreclr/nativeaot/Runtime/AsmOffsets.h index 203fee38bf15ff..30540742974b45 100644 --- a/src/coreclr/nativeaot/Runtime/AsmOffsets.h +++ b/src/coreclr/nativeaot/Runtime/AsmOffsets.h @@ -72,16 +72,6 @@ ASM_OFFSET( 10, 20, InterfaceDispatchCache, m_rgEntries) ASM_SIZEOF( 8, 10, InterfaceDispatchCacheEntry) #endif -#ifdef FEATURE_DYNAMIC_CODE -ASM_OFFSET( 0, 0, CallDescrData, pSrc) -ASM_OFFSET( 4, 8, CallDescrData, numStackSlots) -ASM_OFFSET( 8, C, CallDescrData, fpReturnSize) -ASM_OFFSET( C, 10, CallDescrData, pArgumentRegisters) -ASM_OFFSET( 10, 18, CallDescrData, pFloatArgumentRegisters) -ASM_OFFSET( 14, 20, CallDescrData, pTarget) -ASM_OFFSET( 18, 28, CallDescrData, pReturnBuffer) -#endif - // Undefine macros that are only used in this header for convenience. #undef ASM_OFFSET #undef ASM_SIZEOF diff --git a/src/coreclr/nativeaot/Runtime/AsmOffsetsVerify.cpp b/src/coreclr/nativeaot/Runtime/AsmOffsetsVerify.cpp index 489d10aa9b9b87..705e198aaaca32 100644 --- a/src/coreclr/nativeaot/Runtime/AsmOffsetsVerify.cpp +++ b/src/coreclr/nativeaot/Runtime/AsmOffsetsVerify.cpp @@ -16,7 +16,6 @@ #include "RuntimeInstance.h" #include "CachedInterfaceDispatch.h" #include "shash.h" -#include "CallDescr.h" class AsmOffsets { diff --git a/src/coreclr/nativeaot/Runtime/CMakeLists.txt b/src/coreclr/nativeaot/Runtime/CMakeLists.txt index e836c3f2d391f1..864ad7972b48a8 100644 --- a/src/coreclr/nativeaot/Runtime/CMakeLists.txt +++ b/src/coreclr/nativeaot/Runtime/CMakeLists.txt @@ -196,7 +196,6 @@ endif (CLR_CMAKE_TARGET_ARCH_AMD64 AND CLR_CMAKE_TARGET_WIN32) list(APPEND RUNTIME_SOURCES_ARCH_ASM ${ARCH_SOURCES_DIR}/AllocFast.${ASM_SUFFIX} - ${ARCH_SOURCES_DIR}/CallDescrWorker.${ASM_SUFFIX} ${ARCH_SOURCES_DIR}/ExceptionHandling.${ASM_SUFFIX} ${ARCH_SOURCES_DIR}/GcProbe.${ASM_SUFFIX} ${ARCH_SOURCES_DIR}/Interlocked.${ASM_SUFFIX} diff --git a/src/coreclr/nativeaot/Runtime/CallDescr.h b/src/coreclr/nativeaot/Runtime/CallDescr.h deleted file mode 100644 index 946b96d2c8e7c9..00000000000000 --- a/src/coreclr/nativeaot/Runtime/CallDescr.h +++ /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. - -struct CallDescrData -{ - uint8_t* pSrc; - int numStackSlots; - int fpReturnSize; - uint8_t* pArgumentRegisters; - uint8_t* pFloatArgumentRegisters; - void* pTarget; - void* pReturnBuffer; -}; diff --git a/src/coreclr/nativeaot/Runtime/ICodeManager.h b/src/coreclr/nativeaot/Runtime/ICodeManager.h index 4205c62c4de080..b21aa3fde6be71 100644 --- a/src/coreclr/nativeaot/Runtime/ICodeManager.h +++ b/src/coreclr/nativeaot/Runtime/ICodeManager.h @@ -172,6 +172,8 @@ enum UnwindStackFrameFlags // If this is a reverse P/Invoke frame, do not continue the unwind // after extracting the saved transition frame. USFF_StopUnwindOnTransitionFrame = 1, + // Registers not containing GC roots can be omitted. + USFF_GcUnwind = 2, }; class ICodeManager diff --git a/src/coreclr/nativeaot/Runtime/IntrinsicConstants.h b/src/coreclr/nativeaot/Runtime/IntrinsicConstants.h index 67ba547488e960..41ec8dec9c3d02 100644 --- a/src/coreclr/nativeaot/Runtime/IntrinsicConstants.h +++ b/src/coreclr/nativeaot/Runtime/IntrinsicConstants.h @@ -34,6 +34,10 @@ enum XArchIntrinsicConstants XArchIntrinsicConstants_Avx512dq_vl = 0x400000, XArchIntrinsicConstants_Avx512Vbmi = 0x800000, XArchIntrinsicConstants_Avx512Vbmi_vl = 0x1000000, + XArchIntrinsicConstants_Serialize = 0x2000000, + XArchIntrinsicConstants_VectorT128 = 0x4000000, + XArchIntrinsicConstants_VectorT256 = 0x8000000, + XArchIntrinsicConstants_VectorT512 = 0x10000000, }; #endif //HOST_X86 || HOST_AMD64 @@ -49,6 +53,7 @@ enum ARM64IntrinsicConstants ARM64IntrinsicConstants_Sha256 = 0x0040, ARM64IntrinsicConstants_Atomics = 0x0080, ARM64IntrinsicConstants_Rcpc = 0x0100, + ARM64IntrinsicConstants_VectorT128 = 0x0200, }; // Bit position for the ARM64IntrinsicConstants_Atomics flags, to be used with tbz / tbnz instructions diff --git a/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp b/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp index e073885514555f..da9a5c4b97618f 100644 --- a/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp +++ b/src/coreclr/nativeaot/Runtime/MiscHelpers.cpp @@ -38,6 +38,7 @@ #include "GCMemoryHelpers.h" #include "GCMemoryHelpers.inl" #include "yieldprocessornormalized.h" +#include "RhConfig.h" COOP_PINVOKE_HELPER(void, RhDebugBreak, ()) { @@ -120,16 +121,6 @@ COOP_PINVOKE_HELPER(HANDLE, RhGetOSModuleFromPointer, (PTR_VOID pPointerVal)) return NULL; } -COOP_PINVOKE_HELPER(HANDLE, RhGetOSModuleFromEEType, (MethodTable * pEEType)) -{ - return pEEType->GetTypeManagerPtr()->AsTypeManager()->GetOsModuleHandle(); -} - -COOP_PINVOKE_HELPER(TypeManagerHandle, RhGetModuleFromEEType, (MethodTable * pEEType)) -{ - return *pEEType->GetTypeManagerPtr(); -} - COOP_PINVOKE_HELPER(FC_BOOL_RET, RhFindBlob, (TypeManagerHandle *pTypeManagerHandle, uint32_t blobId, uint8_t ** ppbBlob, uint32_t * pcbBlob)) { TypeManagerHandle typeManagerHandle = *pTypeManagerHandle; @@ -349,18 +340,6 @@ COOP_PINVOKE_HELPER(uint8_t *, RhGetCodeTarget, (uint8_t * pCodeOrg)) return pCodeOrg; } -// Get the universal transition thunk. If the universal transition stub is called through -// the normal PE static linkage model, a jump stub would be used which may interfere with -// the custom calling convention of the universal transition thunk. So instead, a special -// api just for getting the thunk address is needed. -// TODO: On ARM this may still result in a jump stub that trashes R12. Determine if anything -// needs to be done about that when we implement the stub for ARM. -extern "C" void RhpUniversalTransition(); -COOP_PINVOKE_HELPER(void*, RhGetUniversalTransitionThunk, ()) -{ - return (void*)RhpUniversalTransition; -} - extern CrstStatic g_ThunkPoolLock; EXTERN_C NATIVEAOT_API void __cdecl RhpAcquireThunkPoolLock() @@ -422,6 +401,13 @@ COOP_PINVOKE_HELPER(int32_t, RhGetProcessCpuCount, ()) return PalGetProcessCpuCount(); } +COOP_PINVOKE_HELPER(uint32_t, RhGetKnobValues, (char *** pResultKeys, char *** pResultValues)) +{ + *pResultKeys = g_pRhConfig->GetKnobNames(); + *pResultValues = g_pRhConfig->GetKnobValues(); + return g_pRhConfig->GetKnobCount(); +} + #if defined(TARGET_X86) || defined(TARGET_AMD64) EXTERN_C NATIVEAOT_API void __cdecl RhCpuIdEx(int* cpuInfo, int functionId, int subFunctionId) { diff --git a/src/coreclr/nativeaot/Runtime/PalRedhawk.h b/src/coreclr/nativeaot/Runtime/PalRedhawk.h index a718812f23ddce..c30d7d05ec3dbb 100644 --- a/src/coreclr/nativeaot/Runtime/PalRedhawk.h +++ b/src/coreclr/nativeaot/Runtime/PalRedhawk.h @@ -752,8 +752,6 @@ REDHAWK_PALIMPORT uint32_t REDHAWK_PALAPI PalEventUnregister(REGHANDLE arg1); REDHAWK_PALIMPORT uint32_t REDHAWK_PALAPI PalEventWrite(REGHANDLE arg1, const EVENT_DESCRIPTOR * arg2, uint32_t arg3, EVENT_DATA_DESCRIPTOR * arg4); #endif -REDHAWK_PALIMPORT _Ret_maybenull_ void* REDHAWK_PALAPI PalSetWerDataBuffer(_In_ void* pNewBuffer); - REDHAWK_PALIMPORT UInt32_BOOL REDHAWK_PALAPI PalAllocateThunksFromTemplate(_In_ HANDLE hTemplateModule, uint32_t templateRva, size_t templateSize, _Outptr_result_bytebuffer_(templateSize) void** newThunksOut); REDHAWK_PALIMPORT UInt32_BOOL REDHAWK_PALAPI PalFreeThunksFromTemplate(_In_ void *pBaseAddress); diff --git a/src/coreclr/nativeaot/Runtime/RhConfig.cpp b/src/coreclr/nativeaot/Runtime/RhConfig.cpp index 0b965c18994f86..506cf750672bfa 100644 --- a/src/coreclr/nativeaot/Runtime/RhConfig.cpp +++ b/src/coreclr/nativeaot/Runtime/RhConfig.cpp @@ -120,14 +120,8 @@ bool RhConfig::Environment::TryGetStringValue(const char* name, char** value) return true; } -struct CompilerEmbeddedSettingsBlob -{ - uint32_t Size; - char Data[1]; -}; - -extern "C" CompilerEmbeddedSettingsBlob g_compilerEmbeddedSettingsBlob; -extern "C" CompilerEmbeddedSettingsBlob g_compilerEmbeddedKnobsBlob; +extern "C" RhConfig::Config g_compilerEmbeddedSettingsBlob; +extern "C" RhConfig::Config g_compilerEmbeddedKnobsBlob; bool RhConfig::ReadConfigValue(_In_z_ const char *name, uint64_t* pValue, bool decimal) { @@ -136,7 +130,7 @@ bool RhConfig::ReadConfigValue(_In_z_ const char *name, uint64_t* pValue, bool d // Check the embedded configuration const char *embeddedValue = nullptr; - if (GetEmbeddedVariable(&g_embeddedSettings, &g_compilerEmbeddedSettingsBlob, name, true, &embeddedValue)) + if (GetEmbeddedVariable(&g_compilerEmbeddedSettingsBlob, name, true, &embeddedValue)) { *pValue = strtoull(embeddedValue, NULL, decimal ? 10 : 16); return true; @@ -148,7 +142,7 @@ bool RhConfig::ReadConfigValue(_In_z_ const char *name, uint64_t* pValue, bool d bool RhConfig::ReadKnobUInt64Value(_In_z_ const char *name, uint64_t* pValue) { const char *embeddedValue = nullptr; - if (GetEmbeddedVariable(&g_embeddedKnobs, &g_compilerEmbeddedKnobsBlob, name, false, &embeddedValue)) + if (GetEmbeddedVariable(&g_compilerEmbeddedKnobsBlob, name, false, &embeddedValue)) { *pValue = strtoull(embeddedValue, NULL, 10); return true; @@ -160,7 +154,7 @@ bool RhConfig::ReadKnobUInt64Value(_In_z_ const char *name, uint64_t* pValue) bool RhConfig::ReadKnobBooleanValue(_In_z_ const char *name, bool* pValue) { const char *embeddedValue = nullptr; - if (GetEmbeddedVariable(&g_embeddedKnobs, &g_compilerEmbeddedKnobsBlob, name, false, &embeddedValue)) + if (GetEmbeddedVariable(&g_compilerEmbeddedKnobsBlob, name, false, &embeddedValue)) { *pValue = strcmp(embeddedValue, "true") == 0; return true; @@ -169,29 +163,30 @@ bool RhConfig::ReadKnobBooleanValue(_In_z_ const char *name, bool* pValue) return false; } -bool RhConfig::GetEmbeddedVariable(void *volatile * embeddedSettings, void* compilerEmbeddedSettingsBlob, _In_z_ const char* configName, bool caseSensitive, _Out_ const char** configValue) +char** RhConfig::GetKnobNames() { - // Read the config if we haven't yet - if (*embeddedSettings == NULL) - { - ReadEmbeddedSettings(embeddedSettings, compilerEmbeddedSettingsBlob); - } + return g_compilerEmbeddedKnobsBlob.GetKeys(); +} - // Config wasn't read or reading failed - if (*embeddedSettings == CONFIG_INI_NOT_AVAIL) - { - return false; - } +char** RhConfig::GetKnobValues() +{ + return g_compilerEmbeddedKnobsBlob.GetValues(); +} - const ConfigPair* configPairs = (const ConfigPair*)*embeddedSettings; +uint32_t RhConfig::GetKnobCount() +{ + return g_compilerEmbeddedKnobsBlob.GetCount(); +} +bool RhConfig::GetEmbeddedVariable(Config* config, _In_z_ const char* configName, bool caseSensitive, _Out_ const char** configValue) +{ // Find the first name which matches - for (uint32_t iSettings = 0; iSettings < ((CompilerEmbeddedSettingsBlob*)compilerEmbeddedSettingsBlob)->Size; iSettings++) + for (uint32_t iSettings = 0; iSettings < config->GetCount(); iSettings++) { - if ((caseSensitive && strcmp(configName, configPairs[iSettings].Key) == 0) - || (!caseSensitive && _stricmp(configName, configPairs[iSettings].Key) == 0)) + if ((caseSensitive && strcmp(configName, config->GetKeyAt(iSettings)) == 0) + || (!caseSensitive && _stricmp(configName, config->GetKeyAt(iSettings)) == 0)) { - *configValue = configPairs[iSettings].Value; + *configValue = config->GetValueAt(iSettings); return true; } } @@ -200,107 +195,4 @@ bool RhConfig::GetEmbeddedVariable(void *volatile * embeddedSettings, void* comp return false; } -void RhConfig::ReadEmbeddedSettings(void *volatile * embeddedSettings, void* compilerEmbeddedSettingsBlob) -{ - if (*embeddedSettings == NULL) - { - uint32_t size = ((CompilerEmbeddedSettingsBlob*)compilerEmbeddedSettingsBlob)->Size; - char* data = ((CompilerEmbeddedSettingsBlob*)compilerEmbeddedSettingsBlob)->Data; - - //if reading the file contents failed set embeddedSettings to CONFIG_INI_NOT_AVAIL - if (size == 0) - { - //only set if another thread hasn't initialized the buffer yet, otherwise ignore and let the first setter win - PalInterlockedCompareExchangePointer(embeddedSettings, CONFIG_INI_NOT_AVAIL, NULL); - - return; - } - - ConfigPair* iniBuff = new (nothrow) ConfigPair[size]; - if (iniBuff == NULL) - { - //only set if another thread hasn't initialized the buffer yet, otherwise ignore and let the first setter win - PalInterlockedCompareExchangePointer(embeddedSettings, CONFIG_INI_NOT_AVAIL, NULL); - - return; - } - - uint32_t iBuff = 0; - uint32_t iIniBuff = 0; - char* currLine; - - //while we haven't reached the max number of config pairs, or the end of the file, read the next line - while (iBuff < size) - { - currLine = &data[iBuff]; - - //find the end of the line - while ((data[iBuff] != '\0') && (iBuff < size)) - iBuff++; - - //parse the line - //only increment iIniBuff if the parsing succeeded otherwise reuse the config struct - if (ParseConfigLine(&iniBuff[iIniBuff], currLine)) - { - iIniBuff++; - } - - //advance to the next line; - iBuff++; - } - - //if another thread initialized first let the first setter win - //delete the iniBuff to avoid leaking memory - if (PalInterlockedCompareExchangePointer(embeddedSettings, iniBuff, NULL) != NULL) - { - delete[] iniBuff; - } - } - - return; -} - -//Parses one line of config and populates values in the passed in configPair -//returns: true if the parsing was successful, false if the parsing failed. -//NOTE: if the method fails configPair is left in an uninitialized state -bool RhConfig::ParseConfigLine(_Out_ ConfigPair* configPair, _In_z_ const char * line) -{ - uint32_t iLine = 0; - uint32_t iKey = 0; - uint32_t iVal = 0; - - //while we haven't reached the end of the key signalled by '=', or the end of the line, or the key maxlen - while (line[iLine] != '=' && line[iLine] != '\0' && iKey < CONFIG_KEY_MAXLEN) - { - configPair->Key[iKey++] = line[iLine++]; - } - - //if the current char is not '=' we reached the key maxlen, or the line ended return false - if (line[iLine] != '=') - { - return FALSE; - } - - configPair->Key[iKey] = '\0'; - - //increment to start of the value - iLine++; - - //while we haven't reached the end of the line, or val maxlen - while (line[iLine] != '\0' && iVal < CONFIG_VAL_MAXLEN) - { - configPair->Value[iVal++] = line[iLine++]; - } - - //if the current char is not '\0' we didn't reach the end of the line return false - if (line[iLine] != '\0') - { - return FALSE; - } - - configPair->Value[iVal] = '\0'; - - return TRUE; -} - #endif diff --git a/src/coreclr/nativeaot/Runtime/RhConfig.h b/src/coreclr/nativeaot/Runtime/RhConfig.h index a3cd83493cab96..59d1d37fc15546 100644 --- a/src/coreclr/nativeaot/Runtime/RhConfig.h +++ b/src/coreclr/nativeaot/Runtime/RhConfig.h @@ -11,6 +11,8 @@ // Values can also be embedded in the compiled binary. // +#ifndef RHCONFIG_H +#define RHCONFIG_H #ifndef DACCESS_COMPILE @@ -18,26 +20,20 @@ class RhConfig { - -#define CONFIG_INI_NOT_AVAIL (void*)0x1 //signal for ini file failed to load -#define CONFIG_KEY_MAXLEN 50 //arbitrary max length of config keys increase if needed #define CONFIG_VAL_MAXLEN 16 //64 bit uint in hex -private: - struct ConfigPair +public: + struct Config { + uint32_t m_count; + char* m_first[]; public: - char Key[CONFIG_KEY_MAXLEN + 1]; //maxlen + null terminator - char Value[CONFIG_VAL_MAXLEN + 1]; //maxlen + null terminator + uint32_t GetCount() { return m_count; } + char* GetKeyAt(int32_t index) { return m_first[index]; } + char* GetValueAt(int32_t index) { return m_first[m_count + index]; } + char** GetKeys() { return m_first; } + char** GetValues() { return &m_first[m_count]; } }; - // g_embeddedSettings is a buffer of ConfigPair structs embedded in the compiled binary. - // - //NOTE: g_embeddedSettings is only set in ReadEmbeddedSettings and must be set atomically only once - // using PalInterlockedCompareExchangePointer to avoid races when initializing - void* volatile g_embeddedSettings = NULL; - void* volatile g_embeddedKnobs = NULL; - -public: class Environment { public: // static @@ -52,6 +48,10 @@ class RhConfig bool ReadKnobUInt64Value(_In_z_ const char* wszName, uint64_t* pValue); bool ReadKnobBooleanValue(_In_z_ const char* wszName, bool* pValue); + char** GetKnobNames(); + char** GetKnobValues(); + uint32_t GetKnobCount(); + #define DEFINE_VALUE_ACCESSOR(_name, defaultVal) \ uint64_t Get##_name() \ { \ @@ -99,16 +99,9 @@ class RhConfig #define CONFIG_FILE_MAXLEN RCV_Count * sizeof(ConfigPair) + 2000 private: - //Parses one line of config and populates values in the passed in configPair - //returns: true if the parsing was successful, false if the parsing failed. - //NOTE: if the method fails configPair is left in an uninitialized state - bool ParseConfigLine(_Out_ ConfigPair* configPair, _In_z_ const char * line); - - void ReadEmbeddedSettings(void *volatile * embeddedSettings, void* compilerEmbeddedSettingsBlob); - // Gets a pointer to the embedded configuration value. Memory is held by the callee. // Returns true if the variable was found, false otherwise - bool GetEmbeddedVariable(void *volatile * embeddedSettings, void* compilerEmbeddedSettingsBlob, _In_z_ const char* configName, bool caseSensitive, _Out_ const char** configValue); + bool GetEmbeddedVariable(Config* config, _In_z_ const char* configName, bool caseSensitive, _Out_ const char** configValue); uint32_t m_uiConfigValuesRead; uint64_t m_uiConfigValues[RCV_Count]; @@ -117,3 +110,5 @@ class RhConfig extern RhConfig * g_pRhConfig; #endif //!DACCESS_COMPILE + +#endif // RHCONFIG_H diff --git a/src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp b/src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp index 146c15aeff192c..2d1a6971b10fb8 100644 --- a/src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp +++ b/src/coreclr/nativeaot/Runtime/RuntimeInstance.cpp @@ -35,14 +35,6 @@ bool ShouldHijackForGcStress(uintptr_t CallsiteIP, HijackType ht); #include "shash.inl" -#ifndef DACCESS_COMPILE -COOP_PINVOKE_HELPER(uint8_t *, RhSetErrorInfoBuffer, (uint8_t * pNewBuffer)) -{ - return (uint8_t *) PalSetWerDataBuffer(pNewBuffer); -} -#endif // DACCESS_COMPILE - - ThreadStore * RuntimeInstance::GetThreadStore() { return m_pThreadStore; diff --git a/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp b/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp index 3dc6e98dfeb76d..f4a19246e0137d 100644 --- a/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp +++ b/src/coreclr/nativeaot/Runtime/StackFrameIterator.cpp @@ -44,9 +44,6 @@ GVAL_IMPL_INIT(PTR_VOID, g_ReturnFromUniversalTransitionAddr, PointerToReturnFro EXTERN_C PTR_VOID PointerToReturnFromUniversalTransition_DebugStepTailCall; GVAL_IMPL_INIT(PTR_VOID, g_ReturnFromUniversalTransition_DebugStepTailCallAddr, PointerToReturnFromUniversalTransition_DebugStepTailCall); - -EXTERN_C PTR_VOID PointerToReturnFromCallDescrThunk; -GVAL_IMPL_INIT(PTR_VOID, g_ReturnFromCallDescrThunkAddr, PointerToReturnFromCallDescrThunk); #endif #ifdef TARGET_X86 @@ -1200,130 +1197,6 @@ void StackFrameIterator::UnwindUniversalTransitionThunk() #define STACK_ALIGN_SIZE 4 #endif -#ifdef TARGET_AMD64 -struct CALL_DESCR_CONTEXT -{ - uintptr_t Rbp; - uintptr_t Rsi; - uintptr_t Rbx; - uintptr_t IP; -}; -#elif defined(TARGET_ARM) -struct CALL_DESCR_CONTEXT -{ - uintptr_t R4; - uintptr_t R5; - uintptr_t R7; - uintptr_t IP; -}; -#elif defined(TARGET_ARM64) -struct CALL_DESCR_CONTEXT -{ - uintptr_t FP; - uintptr_t IP; - uintptr_t X19; - uintptr_t X20; -}; -#elif defined(TARGET_X86) -struct CALL_DESCR_CONTEXT -{ - uintptr_t Rbx; - uintptr_t Rbp; - uintptr_t IP; -}; -#elif defined (TARGET_WASM) -struct CALL_DESCR_CONTEXT -{ - uintptr_t IP; -}; -#else -#error NYI - For this arch -#endif - -typedef DPTR(CALL_DESCR_CONTEXT) PTR_CALL_DESCR_CONTEXT; - -void StackFrameIterator::UnwindCallDescrThunk() -{ - ASSERT((m_dwFlags & MethodStateCalculated) == 0); - -#if defined(USE_PORTABLE_HELPERS) // @TODO: Corresponding helper code is only defined in assembly code - return; -#else // defined(USE_PORTABLE_HELPERS) - ASSERT(CategorizeUnadjustedReturnAddress(m_ControlPC) == InCallDescrThunk); - - uintptr_t newSP; -#ifdef TARGET_AMD64 - // RBP points to the SP that we want to capture. (This arrangement allows for - // the arguments from this function to be loaded into memory with an adjustment - // to SP, like an alloca - newSP = *(PTR_UIntNative)m_RegDisplay.pRbp; - - PTR_CALL_DESCR_CONTEXT pContext = (PTR_CALL_DESCR_CONTEXT)newSP; - - m_RegDisplay.pRbp = PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, Rbp); - m_RegDisplay.pRsi = PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, Rsi); - m_RegDisplay.pRbx = PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, Rbx); - - // And adjust SP to be the state that it should be in just after returning from - // the CallDescrFunction - newSP += sizeof(CALL_DESCR_CONTEXT); -#elif defined(TARGET_ARM) - // R7 points to the SP that we want to capture. (This arrangement allows for - // the arguments from this function to be loaded into memory with an adjustment - // to SP, like an alloca - newSP = *(PTR_UIntNative)m_RegDisplay.pR7; - PTR_CALL_DESCR_CONTEXT pContext = (PTR_CALL_DESCR_CONTEXT)newSP; - - m_RegDisplay.pR4 = PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, R4); - m_RegDisplay.pR5 = PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, R5); - m_RegDisplay.pR7 = PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, R7); - - // And adjust SP to be the state that it should be in just after returning from - // the CallDescrFunction - newSP += sizeof(CALL_DESCR_CONTEXT); - -#elif defined(TARGET_ARM64) - // pFP points to the SP that we want to capture. (This arrangement allows for - // the arguments from this function to be loaded into memory with an adjustment - // to SP, like an alloca - newSP = *(PTR_UIntNative)m_RegDisplay.pFP; - PTR_CALL_DESCR_CONTEXT pContext = (PTR_CALL_DESCR_CONTEXT)newSP; - - m_RegDisplay.pX19 = PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, X19); - m_RegDisplay.pX20 = PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, X20); - - // And adjust SP to be the state that it should be in just after returning from - // the CallDescrFunction - newSP += sizeof(CALL_DESCR_CONTEXT); - -#elif defined(TARGET_X86) - // RBP points to the SP that we want to capture. (This arrangement allows for - // the arguments from this function to be loaded into memory with an adjustment - // to SP, like an alloca - newSP = *(PTR_UIntNative)m_RegDisplay.pRbp; - - PTR_CALL_DESCR_CONTEXT pContext = (PTR_CALL_DESCR_CONTEXT)(newSP - offsetof(CALL_DESCR_CONTEXT, Rbp)); - - m_RegDisplay.pRbp = PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, Rbp); - m_RegDisplay.pRbx = PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, Rbx); - - // And adjust SP to be the state that it should be in just after returning from - // the CallDescrFunction - newSP += sizeof(CALL_DESCR_CONTEXT) - offsetof(CALL_DESCR_CONTEXT, Rbp); - -#else - PORTABILITY_ASSERT("UnwindCallDescrThunk"); - PTR_CALL_DESCR_CONTEXT pContext = NULL; -#endif - - m_RegDisplay.SetAddrOfIP(PTR_TO_MEMBER(CALL_DESCR_CONTEXT, pContext, IP)); - m_RegDisplay.SetIP(pContext->IP); - m_RegDisplay.SetSP(newSP); - SetControlPC(dac_cast(pContext->IP)); - -#endif // defined(USE_PORTABLE_HELPERS) -} - void StackFrameIterator::UnwindThrowSiteThunk() { ASSERT((m_dwFlags & MethodStateCalculated) == 0); @@ -1442,6 +1315,11 @@ void StackFrameIterator::NextInternal() unwindFlags |= USFF_StopUnwindOnTransitionFrame; } + if ((m_dwFlags & GcStackWalkFlags) == GcStackWalkFlags) + { + unwindFlags |= USFF_GcUnwind; + } + FAILFAST_OR_DAC_FAIL(GetCodeManager()->UnwindStackFrame(&m_methodInfo, unwindFlags, &m_RegDisplay, &m_pPreviousTransitionFrame)); @@ -1654,11 +1532,7 @@ void StackFrameIterator::UnwindNonEHThunkSequence() { ASSERT(m_pConservativeStackRangeLowerBound == NULL); - if (category == InCallDescrThunk) - { - UnwindCallDescrThunk(); - } - else if (category == InUniversalTransitionThunk) + if (category == InUniversalTransitionThunk) { UnwindUniversalTransitionThunk(); ASSERT(m_pConservativeStackRangeLowerBound != NULL); @@ -1851,7 +1725,6 @@ bool StackFrameIterator::IsNonEHThunk(ReturnAddressCategory category) default: return false; case InUniversalTransitionThunk: - case InCallDescrThunk: return true; } } @@ -1921,11 +1794,7 @@ StackFrameIterator::ReturnAddressCategory StackFrameIterator::CategorizeUnadjust #else // defined(USE_PORTABLE_HELPERS) #if defined(FEATURE_DYNAMIC_CODE) - if (EQUALS_RETURN_ADDRESS(returnAddress, ReturnFromCallDescrThunk)) - { - return InCallDescrThunk; - } - else if (EQUALS_RETURN_ADDRESS(returnAddress, ReturnFromUniversalTransition) || + if (EQUALS_RETURN_ADDRESS(returnAddress, ReturnFromUniversalTransition) || EQUALS_RETURN_ADDRESS(returnAddress, ReturnFromUniversalTransition_DebugStepTailCall)) { return InUniversalTransitionThunk; diff --git a/src/coreclr/nativeaot/Runtime/StackFrameIterator.h b/src/coreclr/nativeaot/Runtime/StackFrameIterator.h index 9551e4caeed497..5ea7676cf51e8f 100644 --- a/src/coreclr/nativeaot/Runtime/StackFrameIterator.h +++ b/src/coreclr/nativeaot/Runtime/StackFrameIterator.h @@ -79,10 +79,6 @@ class StackFrameIterator // NOTE: This function always publishes a non-NULL conservative stack range lower bound. void UnwindUniversalTransitionThunk(); - // If our control PC indicates that we're in the call descr thunk that we use to call an arbitrary managed - // function with an arbitrary signature from a normal managed function handle the stack walk specially. - void UnwindCallDescrThunk(); - void EnterInitialInvalidState(Thread * pThreadToWalk); void InternalInit(Thread * pThreadToWalk, PTR_PInvokeTransitionFrame pFrame, uint32_t dwFlags); // GC stackwalk @@ -115,7 +111,6 @@ class StackFrameIterator InThrowSiteThunk, InFuncletInvokeThunk, InFilterFuncletInvokeThunk, - InCallDescrThunk, InUniversalTransitionThunk, }; diff --git a/src/coreclr/nativeaot/Runtime/amd64/CallDescrWorker.S b/src/coreclr/nativeaot/Runtime/amd64/CallDescrWorker.S deleted file mode 100644 index 483d4b5f9ac8cc..00000000000000 --- a/src/coreclr/nativeaot/Runtime/amd64/CallDescrWorker.S +++ /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. - -.intel_syntax noprefix -#include - -NESTED_ENTRY RhCallDescrWorker, _TEXT, NoHandler - - EXPORT_POINTER_TO_ADDRESS PointerToReturnFromCallDescrThunk - - // UNIXTODO: Implement this function - int 3 -NESTED_END RhCallDescrWorker, _TEXT diff --git a/src/coreclr/nativeaot/Runtime/amd64/CallDescrWorker.asm b/src/coreclr/nativeaot/Runtime/amd64/CallDescrWorker.asm deleted file mode 100644 index 3f4ded05d9918e..00000000000000 --- a/src/coreclr/nativeaot/Runtime/amd64/CallDescrWorker.asm +++ /dev/null @@ -1,105 +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 AsmMacros.inc - - -;;;;;;;;;;;;;;;;;;;;;;; CallingConventionConverter Thunks Helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;;extern "C" void RhCallDescrWorker(CallDescrData * pCallDescrData); - - NESTED_ENTRY RhCallDescrWorker, _TEXT - - push_nonvol_reg rbx ; save nonvolatile registers - push_nonvol_reg rsi ; - push_nonvol_reg rbp ; - set_frame rbp, 0 ; set frame pointer - - END_PROLOGUE - - mov rbx, rcx ; save pCallDescrData in rbx - - mov ecx, dword ptr [rbx + OFFSETOF__CallDescrData__numStackSlots] - - test ecx, 1 - jz StackAligned - push rax -StackAligned: - - mov rsi, [rbx + OFFSETOF__CallDescrData__pSrc] ; set source argument list address - lea rsi, [rsi + 8 * rcx] - -StackCopyLoop: ; copy the arguments to stack top-down to carefully probe for sufficient - ; stack space - sub rsi, 8 - push qword ptr [rsi] - dec ecx - jnz StackCopyLoop - - ; - ; N.B. All four argument registers are loaded regardless of the actual number - ; of arguments. - ; - - mov rax, [rbx + OFFSETOF__CallDescrData__pFloatArgumentRegisters] ; get floating pointer arg registers pointer - - mov rcx, 0[rsp] ; load first four argument registers - mov rdx, 8[rsp] ; - mov r8, 10h[rsp] ; - mov r9, 18h[rsp] ; - test rax, rax ; - jz DoCall ; - movdqa xmm0, [rax + 00h] ; load floating point registers if they are used - movdqa xmm1, [rax + 10h] ; - movdqa xmm2, [rax + 20h] ; - movdqa xmm3, [rax + 30h] ; -DoCall: - call qword ptr [rbx + OFFSETOF__CallDescrData__pTarget] ; call target function - - EXPORT_POINTER_TO_ADDRESS PointerToReturnFromCallDescrThunk - - ; Symbol used to identify thunk call to managed function so the special - ; case unwinder can unwind through this function. Sadly we cannot directly - ; export this symbol right now because it confuses DIA unwinder to believe - ; it's the beginning of a new method, therefore we export the address - ; of an auxiliary variable holding the address instead. - - ; Save FP return value - - mov ecx, dword ptr [rbx + OFFSETOF__CallDescrData__fpReturnSize] - test ecx, ecx - jz ReturnsInt - - cmp ecx, 4 - je ReturnsFloat - cmp ecx, 8 - je ReturnsDouble - ; unexpected - jmp Epilog - -ReturnsInt: - mov rbx, [rbx + OFFSETOF__CallDescrData__pReturnBuffer] - mov [rbx], rax - -Epilog: - lea rsp, 0[rbp] ; deallocate argument list - pop rbp ; restore nonvolatile register - pop rsi ; - pop rbx ; - ret - -ReturnsFloat: -; Unlike desktop returnValue is a pointer to a return buffer, not the buffer itself - mov rbx, [rbx + OFFSETOF__CallDescrData__pReturnBuffer] - movss real4 ptr [rbx], xmm0 - jmp Epilog - -ReturnsDouble: -; Unlike desktop returnValue is a pointer to a return buffer, not the buffer itself - mov rbx, [rbx + OFFSETOF__CallDescrData__pReturnBuffer] - movsd real8 ptr [rbx], xmm0 - jmp Epilog - - NESTED_END RhCallDescrWorker, _TEXT - -end diff --git a/src/coreclr/nativeaot/Runtime/arm/CallDescrWorker.S b/src/coreclr/nativeaot/Runtime/arm/CallDescrWorker.S deleted file mode 100644 index 53184d9b28b2a3..00000000000000 --- a/src/coreclr/nativeaot/Runtime/arm/CallDescrWorker.S +++ /dev/null @@ -1,20 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -.syntax unified -.thumb - -#include // generated by the build from AsmOffsets.cpp -#include - -// TODO: Implement Arm support - -NESTED_ENTRY RhCallDescrWorker, _TEXT, NoHandler -LOCAL_LABEL(ReturnFromCallDescrThunk): - - EXPORT_POINTER_TO_ADDRESS PointerToReturnFromCallDescrThunk - - // UNIXTODO: Implement this function - EMIT_BREAKPOINT -NESTED_END RhCallDescrWorker, _TEXT - diff --git a/src/coreclr/nativeaot/Runtime/arm/CallDescrWorker.asm b/src/coreclr/nativeaot/Runtime/arm/CallDescrWorker.asm deleted file mode 100644 index 7ee66320cb3325..00000000000000 --- a/src/coreclr/nativeaot/Runtime/arm/CallDescrWorker.asm +++ /dev/null @@ -1,128 +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 "AsmMacros.h" - - TEXTAREA - -;;----------------------------------------------------------------------------- -;; This helper routine enregisters the appropriate arguments and makes the -;; actual call. -;;----------------------------------------------------------------------------- -;;void RhCallDescrWorker(CallDescrData * pCallDescrData); - NESTED_ENTRY RhCallDescrWorker - PROLOG_PUSH {r4,r5,r7,lr} - PROLOG_STACK_SAVE r7 - - mov r5,r0 ; save pCallDescrData in r5 - - ldr r1, [r5,#OFFSETOF__CallDescrData__numStackSlots] - cbz r1, Ldonestack - - ;; Add frame padding to ensure frame size is a multiple of 8 (a requirement of the OS ABI). - ;; We push four registers (above) and numStackSlots arguments (below). If this comes to an odd number - ;; of slots we must pad with another. This simplifies to "if the low bit of numStackSlots is set, - ;; extend the stack another four bytes". - lsls r2, r1, #2 - and r3, r2, #4 - sub sp, sp, r3 - - ;; This loop copies numStackSlots words - ;; from [pSrcEnd-4,pSrcEnd-8,...] to [sp-4,sp-8,...] - ldr r0, [r5,#OFFSETOF__CallDescrData__pSrc] - add r0,r0,r2 -Lstackloop - ldr r2, [r0,#-4]! - str r2, [sp,#-4]! - subs r1, r1, #1 - bne Lstackloop -Ldonestack - - ;; If FP arguments are supplied in registers (r3 != NULL) then initialize all of them from the pointer - ;; given in r3. Do not use "it" since it faults in floating point even when the instruction is not executed. - ldr r3, [r5,#OFFSETOF__CallDescrData__pFloatArgumentRegisters] - cbz r3, LNoFloatingPoint - vldm r3, {s0-s15} -LNoFloatingPoint - - ;; Copy [pArgumentRegisters, ..., pArgumentRegisters + 12] - ;; into r0, ..., r3 - - ldr r4, [r5,#OFFSETOF__CallDescrData__pArgumentRegisters] - ldm r4, {r0-r3} - - CHECK_STACK_ALIGNMENT - - ;; call pTarget - ;; Note that remoting expect target in r4. - ldr r4, [r5,#OFFSETOF__CallDescrData__pTarget] - blx r4 - - EXPORT_POINTER_TO_ADDRESS PointerToReturnFromCallDescrThunk - - ;; Symbol used to identify thunk call to managed function so the special - ;; case unwinder can unwind through this function. Sadly we cannot directly - ;; export this symbol right now because it confuses DIA unwinder to believe - ;; it's the beginning of a new method, therefore we export the address - ;; of an auxiliary variable holding the address instead. - - ldr r3, [r5,#OFFSETOF__CallDescrData__fpReturnSize] - - ;; Save FP return value if appropriate - cbz r3, LFloatingPointReturnDone - - ;; Float return case - ;; Do not use "it" since it faults in floating point even when the instruction is not executed. - cmp r3, #4 - bne LNoFloatReturn - vmov r0, s0 - b LFloatingPointReturnDone -LNoFloatReturn - - ;; Double return case - ;; Do not use "it" since it faults in floating point even when the instruction is not executed. - cmp r3, #8 - bne LNoDoubleReturn - vmov r0, r1, s0, s1 - b LFloatingPointReturnDone -LNoDoubleReturn -; Unlike desktop returnValue is a pointer to a return buffer, not the buffer itself - ldr r2, [r5, #OFFSETOF__CallDescrData__pReturnBuffer] - - cmp r3, #16 - bne LNoFloatHFAReturn - vstm r2, {s0-s3} - b LReturnDone -LNoFloatHFAReturn - - cmp r3, #32 - bne LNoDoubleHFAReturn - vstm r2, {d0-d3} - b LReturnDone -LNoDoubleHFAReturn - - EMIT_BREAKPOINT ; Unreachable - -LFloatingPointReturnDone - -; Unlike desktop returnValue is a pointer to a return buffer, not the buffer itself - ldr r5, [r5, #OFFSETOF__CallDescrData__pReturnBuffer] - - ;; Save return value into retbuf - str r0, [r5, #(0)] - str r1, [r5, #(4)] - -LReturnDone - -#ifdef _DEBUG - ;; trash the floating point registers to ensure that the HFA return values - ;; won't survive by accident - vldm sp, {d0-d3} -#endif - - EPILOG_STACK_RESTORE r7 - EPILOG_POP {r4,r5,r7,pc} - - NESTED_END RhCallDescrWorker - - END diff --git a/src/coreclr/nativeaot/Runtime/arm64/CallDescrWorker.S b/src/coreclr/nativeaot/Runtime/arm64/CallDescrWorker.S deleted file mode 100644 index fa24f81393ac81..00000000000000 --- a/src/coreclr/nativeaot/Runtime/arm64/CallDescrWorker.S +++ /dev/null @@ -1,140 +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 -#include "AsmOffsets.inc" - -//----------------------------------------------------------------------------- -// This helper routine enregisters the appropriate arguments and makes the -// actual call. -// -// INPUT: x0: pointer to CallDescrData struct -// -//----------------------------------------------------------------------------- -//void RhCallDescrWorker(CallDescrData * pCallDescrData); - NESTED_ENTRY RhCallDescrWorker, _TEXT, NoHandler - - PROLOG_SAVE_REG_PAIR_INDEXED fp, lr, -32 - PROLOG_SAVE_REG_PAIR x19, x20, 16 - - // Save the value of SP before we start pushing any arguments - mov x20, sp - - mov x19, x0 // save pCallDescrData in x19 - - ldr w1, [x19, #OFFSETOF__CallDescrData__numStackSlots] - cbz w1, Ldonestack - - // Add frame padding to ensure frame size is a multiple of 16 (a requirement of the OS ABI). - // We push two registers (above) and numStackSlots arguments (below). If this comes to an odd number - // of slots we must pad with another. This simplifies to "if the low bit of numStackSlots is set, - // extend the stack another eight bytes". - ldr x0, [x19, #OFFSETOF__CallDescrData__pSrc] - add x0, x0, x1, lsl #3 // pSrcEnd=pSrc+8*numStackSlots - ands x2, x1, #1 - beq Lstackloop - - // This loop copies numStackSlots words - // from [pSrcEnd-8,pSrcEnd-16,...] to [sp-8,sp-16,...] - - // Pad and store one stack slot as number of slots are odd - ldr x4, [x0,#-8]! - str x4, [sp,#-16]! - subs x1, x1, #1 - beq Ldonestack -Lstackloop: - ldp x2, x4, [x0,#-16]! - stp x2, x4, [sp,#-16]! - subs x1, x1, #2 - bne Lstackloop -Ldonestack: - - // If FP arguments are supplied in registers (x9 != NULL) then initialize all of them from the pointer - // given in x9. - ldr x9, [x19, #OFFSETOF__CallDescrData__pFloatArgumentRegisters] - cbz x9, LNoFloatingPoint - ldp d0, d1, [x9] - ldp d2, d3, [x9, #16] - ldp d4, d5, [x9, #32] - ldp d6, d7, [x9, #48] -LNoFloatingPoint: - - // Copy [pArgumentRegisters, ..., pArgumentRegisters + 64] - // into x0, ..., x7, x8 - - ldr x9, [x19, #OFFSETOF__CallDescrData__pArgumentRegisters] - ldp x0, x1, [x9] - ldp x2, x3, [x9, #16] - ldp x4, x5, [x9, #32] - ldp x6, x7, [x9, #48] - ldr x8, [x9, #64] - - // call pTarget - ldr x9, [x19, #OFFSETOF__CallDescrData__pTarget] - blr x9 - - EXPORT_POINTER_TO_ADDRESS PointerToReturnFromCallDescrThunk - - // Symbol used to identify thunk call to managed function so the special - // case unwinder can unwind through this function. Sadly we cannot directly - // export this symbol right now because it confuses DIA unwinder to believe - // it's the beginning of a new method, therefore we export the address - // of an auxiliary variable holding the address instead. - - ldr w3, [x19, #OFFSETOF__CallDescrData__fpReturnSize] - - // Unlike desktop returnValue is a pointer to a return buffer, not the buffer itself - ldr x19, [x19, #OFFSETOF__CallDescrData__pReturnBuffer] - - // Int return case - cbz w3, LIntReturn - - // Float return case - cmp w3, #4 - beq LFloatOrDoubleReturn - - // Double return case - cmp w3, #8 - bne LCheckHFAReturn - -LFloatOrDoubleReturn: - str d0, [x19] - b LReturnDone - -LCheckHFAReturn: - cmp w3, #16 - beq LFloatOrDoubleHFAReturn - cmp w3, #32 - beq LFloatOrDoubleHFAReturn - b LNoHFAReturn - -LFloatOrDoubleHFAReturn: - //Single/Double HFAReturn return case - stp d0, d1, [x19, #00] - stp d2, d3, [x19, #16] - b LReturnDone - -LNoHFAReturn: - - EMIT_BREAKPOINT // Unreachable - -LIntReturn: - // Save return value(s) into retbuf for int - stp x0, x1, [x19] - -LReturnDone: - -#ifdef _DEBUG - // Trash the floating point registers to ensure that the HFA return values - // won't survive by accident - ldp d0, d1, [sp] - ldp d2, d3, [sp, #16] -#endif - // Restore the value of SP - mov sp, x20 - - EPILOG_RESTORE_REG_PAIR x19, x20, 16 - EPILOG_RESTORE_REG_PAIR_INDEXED fp, lr, 32 - EPILOG_RETURN - - NESTED_END RhCallDescrWorker diff --git a/src/coreclr/nativeaot/Runtime/arm64/CallDescrWorker.asm b/src/coreclr/nativeaot/Runtime/arm64/CallDescrWorker.asm deleted file mode 100644 index 09eef6d781ebf4..00000000000000 --- a/src/coreclr/nativeaot/Runtime/arm64/CallDescrWorker.asm +++ /dev/null @@ -1,143 +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 "AsmMacros.h" - - TEXTAREA - -;;----------------------------------------------------------------------------- -;; This helper routine enregisters the appropriate arguments and makes the -;; actual call. -;; -;; INPUT: x0: pointer to CallDescrData struct -;; -;;----------------------------------------------------------------------------- -;;void RhCallDescrWorker(CallDescrData * pCallDescrData); - NESTED_ENTRY RhCallDescrWorker - - PROLOG_SAVE_REG_PAIR fp, lr, #-32! - PROLOG_SAVE_REG_PAIR x19, x20, #16 - - ;; Save the value of SP before we start pushing any arguments - mov x20, sp - - mov x19, x0 ; save pCallDescrData in x19 - - ldr w1, [x19, #OFFSETOF__CallDescrData__numStackSlots] - cbz w1, Ldonestack - - ;; Add frame padding to ensure frame size is a multiple of 16 (a requirement of the OS ABI). - ;; We push two registers (above) and numStackSlots arguments (below). If this comes to an odd number - ;; of slots we must pad with another. This simplifies to "if the low bit of numStackSlots is set, - ;; extend the stack another eight bytes". - ldr x0, [x19, #OFFSETOF__CallDescrData__pSrc] - add x0, x0, x1 lsl #3 ; pSrcEnd=pSrc+8*numStackSlots - ands x2, x1, #1 - beq Lstackloop - - ;; This loop copies numStackSlots words - ;; from [pSrcEnd-8,pSrcEnd-16,...] to [sp-8,sp-16,...] - - ;; Pad and store one stack slot as number of slots are odd - ldr x4, [x0,#-8]! - str x4, [sp,#-16]! - subs x1, x1, #1 - beq Ldonestack -Lstackloop - ldp x2, x4, [x0,#-16]! - stp x2, x4, [sp,#-16]! - subs x1, x1, #2 - bne Lstackloop -Ldonestack - - ;; If FP arguments are supplied in registers (x9 != NULL) then initialize all of them from the pointer - ;; given in x9. - ldr x9, [x19, #OFFSETOF__CallDescrData__pFloatArgumentRegisters] - cbz x9, LNoFloatingPoint - ldp d0, d1, [x9] - ldp d2, d3, [x9, #16] - ldp d4, d5, [x9, #32] - ldp d6, d7, [x9, #48] -LNoFloatingPoint - - ;; Copy [pArgumentRegisters, ..., pArgumentRegisters + 64] - ;; into x0, ..., x7, x8 - - ldr x9, [x19, #OFFSETOF__CallDescrData__pArgumentRegisters] - ldp x0, x1, [x9] - ldp x2, x3, [x9, #16] - ldp x4, x5, [x9, #32] - ldp x6, x7, [x9, #48] - ldr x8, [x9, #64] - - ;; call pTarget - ldr x9, [x19, #OFFSETOF__CallDescrData__pTarget] - blr x9 - - EXPORT_POINTER_TO_ADDRESS PointerToReturnFromCallDescrThunk - - ;; Symbol used to identify thunk call to managed function so the special - ;; case unwinder can unwind through this function. Sadly we cannot directly - ;; export this symbol right now because it confuses DIA unwinder to believe - ;; it's the beginning of a new method, therefore we export the address - ;; of an auxiliary variable holding the address instead. - - ldr w3, [x19, #OFFSETOF__CallDescrData__fpReturnSize] - - ;; Unlike desktop returnValue is a pointer to a return buffer, not the buffer itself - ldr x19, [x19, #OFFSETOF__CallDescrData__pReturnBuffer] - - ;; Int return case - cbz w3, LIntReturn - - ;; Float return case - cmp w3, #4 - beq LFloatOrDoubleReturn - - ;; Double return case - cmp w3, #8 - bne LCheckHFAReturn - -LFloatOrDoubleReturn - str d0, [x19] - b LReturnDone - -LCheckHFAReturn - cmp w3, #16 - beq LFloatOrDoubleHFAReturn - cmp w3, #32 - beq LFloatOrDoubleHFAReturn - b LNoHFAReturn - -LFloatOrDoubleHFAReturn - ;;Single/Double HFAReturn return case - stp d0, d1, [x19, #00] - stp d2, d3, [x19, #16] - b LReturnDone - -LNoHFAReturn - - EMIT_BREAKPOINT ; Unreachable - -LIntReturn - ;; Save return value(s) into retbuf for int - stp x0, x1, [x19] - -LReturnDone - -#ifdef _DEBUG - ;; Trash the floating point registers to ensure that the HFA return values - ;; won't survive by accident - ldp d0, d1, [sp] - ldp d2, d3, [sp, #16] -#endif - ;; Restore the value of SP - mov sp, x20 - - EPILOG_RESTORE_REG_PAIR x19, x20, #16 - EPILOG_RESTORE_REG_PAIR fp, lr, #32! - EPILOG_RETURN - - NESTED_END RhCallDescrWorker - - END diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-aot.cpp b/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-aot.cpp index 9bb8d088a8d99b..25272643d18a30 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-aot.cpp +++ b/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-aot.cpp @@ -1,6 +1,24 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#include + +#ifdef __APPLE__ +#include +#endif + +#ifdef __NetBSD__ +#include +#include +#include +#include +#endif + +#ifdef __FreeBSD__ +#include +#include +#endif + #include #ifdef ENABLE_PERFTRACING @@ -13,6 +31,7 @@ bool aot_ipc_get_process_id_disambiguation_key(uint32_t process_id, uint64_t *key); +// Consider moving this code to shared library code. See https://github.com/dotnet/runtime/issues/87069 bool aot_ipc_get_process_id_disambiguation_key( uint32_t process_id, @@ -26,7 +45,54 @@ aot_ipc_get_process_id_disambiguation_key( *key = 0; // Mono implementation, restricted just to Unix -#ifdef TARGET_UNIX +#if defined (__APPLE__) || defined (__FreeBSD__) + // On OS X, we return the process start time expressed in Unix time (the number of seconds + // since the start of the Unix epoch). + struct kinfo_proc info = {}; + size_t size = sizeof (info); + int mib [4] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, process_id }; + + const int result_sysctl = sysctl (mib, sizeof(mib)/sizeof(*mib), &info, &size, NULL, 0); + if (result_sysctl == 0) { +#if defined (__APPLE__) + struct timeval proc_starttime = info.kp_proc.p_starttime; +#else // __FreeBSD__ + struct timeval proc_starttime = info.ki_start; +#endif + long seconds_since_epoch = proc_starttime.tv_sec; + *key = seconds_since_epoch; + return true; + } else { + EP_ASSERT (!"Failed to get start time of a process."); + return false; + } +#elif defined (__NetBSD__) + // On NetBSD, we return the process start time expressed in Unix time (the number of seconds + // since the start of the Unix epoch). + kvm_t *kd; + int cnt; + struct kinfo_proc2 *info; + + kd = kvm_open (NULL, NULL, NULL, KVM_NO_FILES, "kvm_open"); + if (!kd) { + EP_ASSERT (!"Failed to get start time of a process."); + return false; + } + + info = kvm_getproc2 (kd, KERN_PROC_PID, process_id, sizeof (struct kinfo_proc2), &cnt); + if (!info || cnt < 1) { + kvm_close (kd); + EP_ASSERT (!"Failed to get start time of a process."); + return false; + } + + kvm_close (kd); + + long seconds_since_epoch = info->p_ustart_sec; + *key = seconds_since_epoch; + + return true; +#elif defined (__linux__) // Here we read /proc//stat file to get the start time for the process. // We return this value (which is expressed in jiffies since boot time). diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-aot.h b/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-aot.h index aaea67334eb0f4..9a56a52060042c 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-aot.h +++ b/src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-aot.h @@ -13,6 +13,8 @@ #include #include +#include + #undef DS_LOG_ALWAYS_0 #define DS_LOG_ALWAYS_0(msg) do {} while (0) @@ -127,8 +129,10 @@ ds_rt_config_value_get_enable (void) { STATIC_CONTRACT_NOTHROW; - // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase - // TODO: EventPipe Configuration values - RhConfig? + bool value; + if (RhConfig::Environment::TryGetBooleanValue("EnableDiagnostics", &value)) + return value; + return true; } @@ -137,8 +141,12 @@ inline ep_char8_t * ds_rt_config_value_get_ports (void) { - // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase - // TODO: EventPipe Configuration values - RhConfig? + STATIC_CONTRACT_NOTHROW; + + char* value; + if (RhConfig::Environment::TryGetStringValue("DiagnosticPorts", &value)) + return (ep_char8_t*)value; + return nullptr; } @@ -148,8 +156,14 @@ uint32_t ds_rt_config_value_get_default_port_suspend (void) { STATIC_CONTRACT_NOTHROW; - // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase - // TODO: EventPipe Configuration values - RhConfig? + + uint64_t value; + if (RhConfig::Environment::TryGetIntegerValue("DefaultDiagnosticPortSuspend", &value)) + { + EP_ASSERT(value <= UINT32_MAX); + return static_cast(value); + } + return 0; } @@ -281,10 +295,15 @@ ds_rt_server_log_pause_message (void) { STATIC_CONTRACT_NOTHROW; - const char diagPortsName[] = "DOTNET_DiagnosticPorts"; - // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase - // TODO: Cannot find nocache versions of RhConfig - // PalDebugBreak(); + ep_char8_t * ports = ds_rt_config_value_get_ports (); + uint32_t port_suspended = ds_rt_config_value_get_default_port_suspend (); + + printf ("The runtime has been configured to pause during startup and is awaiting a Diagnostics IPC ResumeStartup command from a Diagnostic Port.\n"); + printf ("DOTNET_DiagnosticPorts=\"%s\"\n", ports == nullptr ? "" : ports); + printf ("DOTNET_DefaultDiagnosticPortSuspend=%d\n", port_suspended); + fflush (stdout); + + ep_rt_utf8_string_free (ports); } #endif /* ENABLE_PERFTRACING */ diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp index c629f2b86c5eb6..f7793b4065f535 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp +++ b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.cpp @@ -90,13 +90,22 @@ ep_rt_aot_entrypoint_assembly_name_get_utf8 (void) { // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase // TODO: Implement EventPipe assembly name - return filename in nativeaot? - PalDebugBreak(); - - // fallback to the empty string if we can't get assembly info, e.g., if the runtime is - // suspended before an assembly is loaded. return reinterpret_cast(""); } +const ep_char8_t * +ep_rt_aot_diagnostics_command_line_get (void) +{ + // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase + // TODO: revisit commandline for AOT +#ifdef TARGET_WINDOWS + const ep_char16_t* command_line = reinterpret_cast(::GetCommandLineW()); + return ep_rt_utf16_to_utf8_string(command_line, -1); +#else + return ""; +#endif +} + uint32_t ep_rt_aot_atomic_inc_uint32_t (volatile uint32_t *value) { diff --git a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.h b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.h index d17566514a379f..2687fc8f35ed50 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.h +++ b/src/coreclr/nativeaot/Runtime/eventpipe/ep-rt-aot.h @@ -20,6 +20,7 @@ #include "rhassert.h" #include +#include #ifdef TARGET_UNIX #define sprintf_s snprintf @@ -47,6 +48,9 @@ #undef EP_ALIGN_UP #define EP_ALIGN_UP(val,align) _rt_aot_align_up(val,align) +#define _TEXT(s) #s +#define STRINGIFY(s) _TEXT(s) + #ifdef TARGET_UNIX extern pthread_key_t eventpipe_tls_key; extern __thread EventPipeThreadHolder* eventpipe_tls_instance; @@ -88,12 +92,11 @@ ep_rt_entrypoint_assembly_name_get_utf8 (void) static const ep_char8_t * -ep_rt_runtime_version_get_utf8 (void) { +ep_rt_runtime_version_get_utf8 (void) +{ STATIC_CONTRACT_NOTHROW; - // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase - // TODO: Find a way to use CoreCLR runtime_version.h here if a more exact version is needed - return reinterpret_cast("8.0.0"); + return reinterpret_cast(STRINGIFY(RuntimeProductVersion)); } /* @@ -1388,10 +1391,7 @@ ep_rt_utf8_to_utf16le_string ( // Shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase // Implementation would just use strlen and malloc to make a new buffer, and would then copy the string chars one by one. // Assumes that only ASCII is used for ep_char8_t - size_t len_utf8 = strlen(str); - if (len_utf8 == 0) - return NULL; - + size_t len_utf8 = strlen(str); ep_char16_t *str_utf16 = reinterpret_cast(malloc ((len_utf8 + 1) * sizeof (ep_char16_t))); if (!str_utf16) return NULL; @@ -1511,16 +1511,9 @@ static const ep_char8_t * ep_rt_diagnostics_command_line_get (void) { - STATIC_CONTRACT_NOTHROW; - - // shipping criteria: no EVENTPIPE-NATIVEAOT-TODO left in the codebase - // TODO: revisit commandline for AOT - // return reinterpret_cast(::GetCommandLineA()); - - extern ep_char8_t *volatile _ep_rt_aot_diagnostics_cmd_line; - ep_char8_t *old_cmd_line = _ep_rt_aot_diagnostics_cmd_line; - return _ep_rt_aot_diagnostics_cmd_line; + extern const ep_char8_t * ep_rt_aot_diagnostics_command_line_get (void); + return ep_rt_aot_diagnostics_command_line_get(); } /* diff --git a/src/coreclr/nativeaot/Runtime/i386/CallDescrWorker.asm b/src/coreclr/nativeaot/Runtime/i386/CallDescrWorker.asm deleted file mode 100644 index 481cba1d898863..00000000000000 --- a/src/coreclr/nativeaot/Runtime/i386/CallDescrWorker.asm +++ /dev/null @@ -1,96 +0,0 @@ -;; Licensed to the .NET Foundation under one or more agreements. -;; The .NET Foundation licenses this file to you under the MIT license. - - .586 - .model flat - option casemap:none - .code - -include AsmMacros.inc - -ifdef FEATURE_DYNAMIC_CODE -;;;;;;;;;;;;;;;;;;;;;;; CallingConventionConverter Thunks Helpers ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -;------------------------------------------------------------------------------ -; This helper routine enregisters the appropriate arguments and makes the -; actual call. -;------------------------------------------------------------------------------ -; void __fastcall CallDescrWorker(CallDescrWorkerParams * pParams) -FASTCALL_FUNC RhCallDescrWorker, 4 - push ebp - mov ebp, esp - push ebx - mov ebx, ecx - - mov ecx, [ebx + OFFSETOF__CallDescrData__numStackSlots] - mov eax, [ebx + OFFSETOF__CallDescrData__pSrc] ; copy the stack - test ecx, ecx - jz donestack - lea eax, [eax + 4 * ecx - 4] ; last argument - push dword ptr [eax] - dec ecx - jz donestack - sub eax, 4 - push dword ptr [eax] - dec ecx - jz donestack -stackloop: - sub eax, 4 - push dword ptr [eax] - dec ecx - jnz stackloop -donestack: - - ; now we must push each field of the ArgumentRegister structure - mov eax, [ebx + OFFSETOF__CallDescrData__pArgumentRegisters] - mov edx, dword ptr [eax] - mov ecx, dword ptr [eax + 4] - mov eax,[ebx + OFFSETOF__CallDescrData__pTarget] - call eax - - EXPORT_POINTER_TO_ADDRESS _PointerToReturnFromCallDescrThunk - - ; Symbol used to identify thunk call to managed function so the special - ; case unwinder can unwind through this function. Sadly we cannot directly - ; export this symbol right now because it confuses DIA unwinder to believe - ; it's the beginning of a new method, therefore we export the address - ; by means of an auxiliary variable. - - ; Save FP return value if necessary - mov ecx, [ebx + OFFSETOF__CallDescrData__fpReturnSize] - cmp ecx, 0 - je ReturnsInt - - cmp ecx, 4 - je ReturnsFloat - cmp ecx, 8 - je ReturnsDouble - ; unexpected - jmp Epilog - -ReturnsInt: -; Unlike desktop returnValue is a pointer to a return buffer, not the buffer itself - mov ebx, [ebx + OFFSETOF__CallDescrData__pReturnBuffer] - mov [ebx], eax - mov [ebx + 4], edx - -Epilog: - pop ebx - pop ebp - retn - -ReturnsFloat: - mov ebx, [ebx + OFFSETOF__CallDescrData__pReturnBuffer] - fstp dword ptr [ebx] ; Spill the Float return value - jmp Epilog - -ReturnsDouble: - mov ebx, [ebx + OFFSETOF__CallDescrData__pReturnBuffer] - fstp qword ptr [ebx] ; Spill the Double return value - jmp Epilog - -FASTCALL_ENDFUNC - -endif - -end diff --git a/src/coreclr/nativeaot/Runtime/portable.cpp b/src/coreclr/nativeaot/Runtime/portable.cpp index c8f43790085b9e..25eb9485fde57c 100644 --- a/src/coreclr/nativeaot/Runtime/portable.cpp +++ b/src/coreclr/nativeaot/Runtime/portable.cpp @@ -394,12 +394,6 @@ void * ReturnFromUniversalTransition_DebugStepTailCall; #endif // USE_PORTABLE_HELPERS -// @TODO Implement CallDescrThunk -EXTERN_C void * ReturnFromCallDescrThunk; -#ifdef USE_PORTABLE_HELPERS -void * ReturnFromCallDescrThunk; -#endif - #if defined(USE_PORTABLE_HELPERS) // // Return address hijacking @@ -462,14 +456,6 @@ COOP_PINVOKE_HELPER(int64_t, RhpLockCmpXchg64, (int64_t * location, int64_t valu return PalInterlockedCompareExchange64(location, value, comparand); } -#endif // USE_PORTABLE_HELPERS - -COOP_PINVOKE_HELPER(void, RhpMemoryBarrier, ()) -{ - PalMemoryBarrier(); -} - -#if defined(USE_PORTABLE_HELPERS) EXTERN_C NATIVEAOT_API void* __cdecl RhAllocateThunksMapping() { return NULL; @@ -516,11 +502,6 @@ COOP_PINVOKE_HELPER(int, RhpGetThunkBlockSize, ()) return 0; } -COOP_PINVOKE_HELPER(void, RhCallDescrWorker, (void * callDescr)) -{ - ASSERT_UNCONDITIONALLY("NYI"); -} - COOP_PINVOKE_HELPER(void *, RhGetCommonStubAddress, ()) { ASSERT_UNCONDITIONALLY("NYI"); diff --git a/src/coreclr/nativeaot/Runtime/startup.cpp b/src/coreclr/nativeaot/Runtime/startup.cpp index a178a11d102fae..58740157c49609 100644 --- a/src/coreclr/nativeaot/Runtime/startup.cpp +++ b/src/coreclr/nativeaot/Runtime/startup.cpp @@ -197,51 +197,59 @@ bool DetectCPUFeatures() { __cpuid(cpuidInfo, 0x00000001); - if (((cpuidInfo[CPUID_EDX] & (1 << 25)) != 0) && ((cpuidInfo[CPUID_EDX] & (1 << 26)) != 0)) // SSE & SSE2 + const int requiredBaselineEdxFlags = (1 << 25) // SSE + | (1 << 26); // SSE2 + + if ((cpuidInfo[CPUID_EDX] & requiredBaselineEdxFlags) == requiredBaselineEdxFlags) { - if ((cpuidInfo[CPUID_ECX] & (1 << 25)) != 0) // AESNI + g_cpuFeatures |= XArchIntrinsicConstants_VectorT128; + + if ((cpuidInfo[CPUID_ECX] & (1 << 25)) != 0) // AESNI { g_cpuFeatures |= XArchIntrinsicConstants_Aes; } - if ((cpuidInfo[CPUID_ECX] & (1 << 1)) != 0) // PCLMULQDQ + if ((cpuidInfo[CPUID_ECX] & (1 << 1)) != 0) // PCLMULQDQ { g_cpuFeatures |= XArchIntrinsicConstants_Pclmulqdq; } - if ((cpuidInfo[CPUID_ECX] & (1 << 0)) != 0) // SSE3 + if ((cpuidInfo[CPUID_ECX] & (1 << 0)) != 0) // SSE3 { g_cpuFeatures |= XArchIntrinsicConstants_Sse3; - if ((cpuidInfo[CPUID_ECX] & (1 << 9)) != 0) // SSSE3 + if ((cpuidInfo[CPUID_ECX] & (1 << 9)) != 0) // SSSE3 { g_cpuFeatures |= XArchIntrinsicConstants_Ssse3; - if ((cpuidInfo[CPUID_ECX] & (1 << 19)) != 0) // SSE4.1 + if ((cpuidInfo[CPUID_ECX] & (1 << 19)) != 0) // SSE4.1 { g_cpuFeatures |= XArchIntrinsicConstants_Sse41; - if ((cpuidInfo[CPUID_ECX] & (1 << 20)) != 0) // SSE4.2 + if ((cpuidInfo[CPUID_ECX] & (1 << 20)) != 0) // SSE4.2 { g_cpuFeatures |= XArchIntrinsicConstants_Sse42; - if ((cpuidInfo[CPUID_ECX] & (1 << 22)) != 0) // MOVBE + if ((cpuidInfo[CPUID_ECX] & (1 << 22)) != 0) // MOVBE { g_cpuFeatures |= XArchIntrinsicConstants_Movbe; } - if ((cpuidInfo[CPUID_ECX] & (1 << 23)) != 0) // POPCNT + if ((cpuidInfo[CPUID_ECX] & (1 << 23)) != 0) // POPCNT { g_cpuFeatures |= XArchIntrinsicConstants_Popcnt; } - if (((cpuidInfo[CPUID_ECX] & (1 << 27)) != 0) && ((cpuidInfo[CPUID_ECX] & (1 << 28)) != 0)) // OSXSAVE & AVX + const int requiredAvxEcxFlags = (1 << 27) // OSXSAVE + | (1 << 28); // AVX + + if ((cpuidInfo[CPUID_ECX] & requiredAvxEcxFlags) == requiredAvxEcxFlags) { - if (PalIsAvxEnabled() && (xmmYmmStateSupport() == 1)) + if (PalIsAvxEnabled() && (xmmYmmStateSupport() == 1)) // XGETBV == 11 { g_cpuFeatures |= XArchIntrinsicConstants_Avx; - if ((cpuidInfo[CPUID_ECX] & (1 << 12)) != 0) // FMA + if ((cpuidInfo[CPUID_ECX] & (1 << 12)) != 0) // FMA { g_cpuFeatures |= XArchIntrinsicConstants_Fma; } @@ -250,66 +258,69 @@ bool DetectCPUFeatures() { __cpuidex(cpuidInfo, 0x00000007, 0x00000000); - if ((cpuidInfo[CPUID_EBX] & (1 << 5)) != 0) // AVX2 + if ((cpuidInfo[CPUID_EBX] & (1 << 5)) != 0) // AVX2 { g_cpuFeatures |= XArchIntrinsicConstants_Avx2; + g_cpuFeatures |= XArchIntrinsicConstants_VectorT256; - __cpuidex(cpuidInfo, 0x00000007, 0x00000001); - if ((cpuidInfo[CPUID_EAX] & (1 << 4)) != 0) // AVX-VNNI + if (PalIsAvx512Enabled() && (avx512StateSupport() == 1)) // XGETBV XRC0[7:5] == 111 { - g_cpuFeatures |= XArchIntrinsicConstants_AvxVnni; - } - - if (PalIsAvx512Enabled() && (avx512StateSupport() == 1)) // XGETBV XRC0[7:5] == 111 - { - if ((cpuidInfo[CPUID_EBX] & (1 << 16)) != 0) // AVX512F + if ((cpuidInfo[CPUID_EBX] & (1 << 16)) != 0) // AVX512F { g_cpuFeatures |= XArchIntrinsicConstants_Avx512f; + g_cpuFeatures |= XArchIntrinsicConstants_VectorT512; bool isAVX512_VLSupported = false; - if ((cpuidInfo[CPUID_EBX] & (1 << 31)) != 0) // AVX512VL + if ((cpuidInfo[CPUID_EBX] & (1 << 31)) != 0) // AVX512VL { g_cpuFeatures |= XArchIntrinsicConstants_Avx512f_vl; isAVX512_VLSupported = true; } - if ((cpuidInfo[CPUID_EBX] & (1 << 30)) != 0) // AVX512BW + if ((cpuidInfo[CPUID_EBX] & (1 << 30)) != 0) // AVX512BW { g_cpuFeatures |= XArchIntrinsicConstants_Avx512bw; - if (isAVX512_VLSupported) + if (isAVX512_VLSupported) // AVX512BW_VL { g_cpuFeatures |= XArchIntrinsicConstants_Avx512bw_vl; } } - if ((cpuidInfo[CPUID_EBX] & (1 << 28)) != 0) // AVX512CD + if ((cpuidInfo[CPUID_EBX] & (1 << 28)) != 0) // AVX512CD { g_cpuFeatures |= XArchIntrinsicConstants_Avx512cd; - if (isAVX512_VLSupported) + if (isAVX512_VLSupported) // AVX512CD_VL { g_cpuFeatures |= XArchIntrinsicConstants_Avx512cd_vl; } } - if ((cpuidInfo[CPUID_EBX] & (1 << 17)) != 0) // AVX512DQ + if ((cpuidInfo[CPUID_EBX] & (1 << 17)) != 0) // AVX512DQ { g_cpuFeatures |= XArchIntrinsicConstants_Avx512dq; - if (isAVX512_VLSupported) + if (isAVX512_VLSupported) // AVX512DQ_VL { g_cpuFeatures |= XArchIntrinsicConstants_Avx512dq_vl; } } - if ((cpuidInfo[CPUID_ECX] & (1 << 1)) != 0) // AVX512VBMI + if ((cpuidInfo[CPUID_ECX] & (1 << 1)) != 0) // AVX512VBMI { g_cpuFeatures |= XArchIntrinsicConstants_Avx512Vbmi; - if (isAVX512_VLSupported) + if (isAVX512_VLSupported) // AVX512VBMI_VL { g_cpuFeatures |= XArchIntrinsicConstants_Avx512Vbmi_vl; } } } } + + __cpuidex(cpuidInfo, 0x00000007, 0x00000001); + + if ((cpuidInfo[CPUID_EAX] & (1 << 4)) != 0) // AVX-VNNI + { + g_cpuFeatures |= XArchIntrinsicConstants_AvxVnni; + } } } } @@ -333,6 +344,11 @@ bool DetectCPUFeatures() { g_cpuFeatures |= XArchIntrinsicConstants_Bmi2; } + + if ((cpuidInfo[CPUID_EDX] & (1 << 14)) != 0) + { + g_cpuFeatures |= XArchIntrinsicConstants_Serialize; // SERIALIZE + } } } diff --git a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp index a856be48f4ab8c..bbe70ae48cd6c0 100644 --- a/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp +++ b/src/coreclr/nativeaot/Runtime/unix/PalRedhawkUnix.cpp @@ -892,12 +892,6 @@ REDHAWK_PALEXPORT void PalFlushInstructionCache(_In_ void* pAddress, size_t size #endif } -REDHAWK_PALEXPORT _Ret_maybenull_ void* REDHAWK_PALAPI PalSetWerDataBuffer(_In_ void* pNewBuffer) -{ - static void* pBuffer; - return PalInterlockedExchangePointer(&pBuffer, pNewBuffer); -} - extern "C" HANDLE GetCurrentProcess() { return (HANDLE)-1; @@ -1446,7 +1440,7 @@ REDHAWK_PALEXPORT void REDHAWK_PALAPI PAL_GetCpuCapabilityFlags(int* flags) #endif #ifdef HWCAP_ASIMD if (hwCap & HWCAP_ASIMD) - *flags |= ARM64IntrinsicConstants_AdvSimd; + *flags |= ARM64IntrinsicConstants_AdvSimd | ARM64IntrinsicConstants_VectorT128; #endif #ifdef HWCAP_ASIMDRDM if (hwCap & HWCAP_ASIMDRDM) @@ -1545,7 +1539,7 @@ REDHAWK_PALEXPORT void REDHAWK_PALAPI PAL_GetCpuCapabilityFlags(int* flags) // Every ARM64 CPU should support SIMD and FP // If the OS have no function to query for CPU capabilities we set just these - *flags |= ARM64IntrinsicConstants_AdvSimd; + *flags |= ARM64IntrinsicConstants_AdvSimd | ARM64IntrinsicConstants_VectorT128; #endif // HAVE_AUXV_HWCAP_H } #endif diff --git a/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp b/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp index 96cc1e3934ef45..cc409cf2167a16 100644 --- a/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp +++ b/src/coreclr/nativeaot/Runtime/windows/CoffNativeCodeManager.cpp @@ -590,9 +590,9 @@ bool CoffNativeCodeManager::UnwindStackFrame(MethodInfo * pMethodInfo, #define WORDPTR PDWORD #elif defined(TARGET_AMD64) #define FOR_EACH_NONVOLATILE_REGISTER(F) \ - F(Rax, pRax) F(Rcx, pRcx) F(Rdx, pRdx) F(Rbx, pRbx) F(Rbp, pRbp) F(Rsi, pRsi) F(Rdi, pRdi) \ - F(R8, pR8) F(R9, pR9) F(R10, pR10) F(R11, pR11) F(R12, pR12) F(R13, pR13) F(R14, pR14) F(R15, pR15) - #define WORDPTR PDWORD64 + F(Rbx, pRbx) F(Rbp, pRbp) F(Rsi, pRsi) F(Rdi, pRdi) \ + F(R12, pR12) F(R13, pR13) F(R14, pR14) F(R15, pR15) +#define WORDPTR PDWORD64 #elif defined(TARGET_ARM64) #define FOR_EACH_NONVOLATILE_REGISTER(F) \ F(X19, pX19) F(X20, pX20) F(X21, pX21) F(X22, pX22) F(X23, pX23) F(X24, pX24) \ @@ -612,7 +612,11 @@ bool CoffNativeCodeManager::UnwindStackFrame(MethodInfo * pMethodInfo, #if defined(TARGET_X86) PORTABILITY_ASSERT("CoffNativeCodeManager::UnwindStackFrame"); #elif defined(TARGET_AMD64) - memcpy(&context.Xmm6, pRegisterSet->Xmm, sizeof(pRegisterSet->Xmm)); + + if (!(flags & USFF_GcUnwind)) + { + memcpy(&context.Xmm6, pRegisterSet->Xmm, sizeof(pRegisterSet->Xmm)); + } context.Rsp = pRegisterSet->SP; context.Rip = pRegisterSet->IP; @@ -634,10 +638,16 @@ bool CoffNativeCodeManager::UnwindStackFrame(MethodInfo * pMethodInfo, pRegisterSet->pIP = PTR_PCODE(pRegisterSet->SP - sizeof(TADDR)); - memcpy(pRegisterSet->Xmm, &context.Xmm6, sizeof(pRegisterSet->Xmm)); + if (!(flags & USFF_GcUnwind)) + { + memcpy(pRegisterSet->Xmm, &context.Xmm6, sizeof(pRegisterSet->Xmm)); + } #elif defined(TARGET_ARM64) - for (int i = 8; i < 16; i++) - context.V[i].Low = pRegisterSet->D[i - 8]; + if (!(flags & USFF_GcUnwind)) + { + for (int i = 8; i < 16; i++) + context.V[i].Low = pRegisterSet->D[i - 8]; + } context.Sp = pRegisterSet->SP; context.Pc = pRegisterSet->IP; @@ -659,8 +669,11 @@ bool CoffNativeCodeManager::UnwindStackFrame(MethodInfo * pMethodInfo, pRegisterSet->pIP = contextPointers.Lr; - for (int i = 8; i < 16; i++) - pRegisterSet->D[i - 8] = context.V[i].Low; + if (!(flags & USFF_GcUnwind)) + { + for (int i = 8; i < 16; i++) + pRegisterSet->D[i - 8] = context.V[i].Low; + } #endif // defined(TARGET_X86) FOR_EACH_NONVOLATILE_REGISTER(CONTEXT_TO_REGDISPLAY); diff --git a/src/coreclr/nativeaot/Runtime/windows/PalRedhawkInline.h b/src/coreclr/nativeaot/Runtime/windows/PalRedhawkInline.h index c6ed7d641a20bf..1d9f7bd1711d62 100644 --- a/src/coreclr/nativeaot/Runtime/windows/PalRedhawkInline.h +++ b/src/coreclr/nativeaot/Runtime/windows/PalRedhawkInline.h @@ -1,6 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if defined(HOST_ARM64) +#include +#endif + // Implementation of Redhawk PAL inline functions EXTERN_C long __cdecl _InterlockedIncrement(long volatile *); @@ -121,7 +125,6 @@ EXTERN_C void __faststorefence(); #pragma intrinsic(__faststorefence) #define PalMemoryBarrier() __faststorefence() - #elif defined(HOST_ARM) EXTERN_C void __yield(void); @@ -130,11 +133,11 @@ EXTERN_C void __dmb(unsigned int _Type); #pragma intrinsic(__dmb) FORCEINLINE void PalYieldProcessor() { - __dmb(0xA /* _ARM_BARRIER_ISHST */); + __dmb(_ARM_BARRIER_ISHST); __yield(); } -#define PalMemoryBarrier() __dmb(0xF /* _ARM_BARRIER_SY */) +#define PalMemoryBarrier() __dmb(_ARM_BARRIER_ISH) #elif defined(HOST_ARM64) @@ -144,11 +147,11 @@ EXTERN_C void __dmb(unsigned int _Type); #pragma intrinsic(__dmb) FORCEINLINE void PalYieldProcessor() { - __dmb(0xA /* _ARM64_BARRIER_ISHST */); + __dmb(_ARM64_BARRIER_ISHST); __yield(); } -#define PalMemoryBarrier() __dmb(0xF /* _ARM64_BARRIER_SY */) +#define PalMemoryBarrier() __dmb(_ARM64_BARRIER_ISH) #else #error Unsupported architecture diff --git a/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp b/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp index c7b1f3e313fa39..6691df67ada460 100644 --- a/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp +++ b/src/coreclr/nativeaot/Runtime/windows/PalRedhawkMinWin.cpp @@ -769,12 +769,6 @@ REDHAWK_PALEXPORT void PalFlushInstructionCache(_In_ void* pAddress, size_t size FlushInstructionCache(GetCurrentProcess(), pAddress, size); } -REDHAWK_PALEXPORT _Ret_maybenull_ void* REDHAWK_PALAPI PalSetWerDataBuffer(_In_ void* pNewBuffer) -{ - static void* pBuffer; - return InterlockedExchangePointer(&pBuffer, pNewBuffer); -} - #if defined(HOST_ARM64) #include "IntrinsicConstants.h" @@ -796,7 +790,7 @@ REDHAWK_PALIMPORT void REDHAWK_PALAPI PAL_GetCpuCapabilityFlags(int* flags) #endif // FP and SIMD support are enabled by default - *flags |= ARM64IntrinsicConstants_AdvSimd; + *flags |= ARM64IntrinsicConstants_AdvSimd | ARM64IntrinsicConstants_VectorT128; if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE)) { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs index 9d46a80d656aac..39fda81c8a8388 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs @@ -195,9 +195,9 @@ public static IntPtr GetPointerFromTypeHandle(RuntimeTypeHandle typeHandle) return typeHandle.ToEETypePtr().RawValue; } - public static TypeManagerHandle GetModuleFromTypeHandle(RuntimeTypeHandle typeHandle) + public static unsafe TypeManagerHandle GetModuleFromTypeHandle(RuntimeTypeHandle typeHandle) { - return RuntimeImports.RhGetModuleFromEEType(GetPointerFromTypeHandle(typeHandle)); + return typeHandle.ToMethodTable()->TypeManager; } public static RuntimeTypeHandle CreateRuntimeTypeHandle(IntPtr ldTokenResult) @@ -817,21 +817,6 @@ public static string TryGetMethodDisplayStringFromIp(IntPtr ip) private static volatile ReflectionExecutionDomainCallbacks s_reflectionExecutionDomainCallbacks; private static TypeLoaderCallbacks s_typeLoaderCallbacks; - public static void ReportUnhandledException(Exception exception) - { - RuntimeExceptionHelpers.ReportUnhandledException(exception); - } - - public static unsafe RuntimeTypeHandle GetRuntimeTypeHandleFromObjectReference(object obj) - { - return new RuntimeTypeHandle(obj.GetEETypePtr()); - } - - public static IntPtr GetUniversalTransitionThunk() - { - return RuntimeImports.RhGetUniversalTransitionThunk(); - } - public static object CreateThunksHeap(IntPtr commonStubAddress) { object newHeap = RuntimeImports.RhCreateThunksHeap(commonStubAddress); @@ -868,22 +853,6 @@ public static int GetThunkSize() return RuntimeImports.RhGetThunkSize(); } - [DebuggerStepThrough] - /* TEMP workaround due to bug 149078 */ - [MethodImpl(MethodImplOptions.NoInlining)] - public static void CallDescrWorker(IntPtr callDescr) - { - RuntimeImports.RhCallDescrWorker(callDescr); - } - - [DebuggerStepThrough] - /* TEMP workaround due to bug 149078 */ - [MethodImpl(MethodImplOptions.NoInlining)] - public static void CallDescrWorkerNative(IntPtr callDescr) - { - RuntimeImports.RhCallDescrWorkerNative(callDescr); - } - public static Delegate CreateObjectArrayDelegate(Type delegateType, Func invoker) { return Delegate.CreateObjectArrayDelegate(delegateType, invoker); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/AppContext.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/AppContext.NativeAot.cs index 830ae290d5a2c9..535eb123ddf0f3 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/AppContext.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/AppContext.NativeAot.cs @@ -1,13 +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.Collections.Generic; using System.Runtime; using System.Runtime.ExceptionServices; +using System.Text; namespace System { public static partial class AppContext { + private static unsafe Dictionary InitializeDataStore() + { + uint count = RuntimeImports.RhGetKnobValues(out byte** keys, out byte** values); + + var dataStore = new Dictionary((int)count); + for (int i = 0; i < count; i++) + { + dataStore.Add( + Encoding.UTF8.GetString(keys[i], string.strlen(keys[i])), + Encoding.UTF8.GetString(values[i], string.strlen(values[i]))); + } + + return dataStore; + } + [RuntimeExport("OnFirstChanceException")] internal static void OnFirstChanceException(object e) { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Attribute.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Attribute.NativeAot.cs index f7604612b5ad5e..fe6505f24c9c90 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Attribute.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Attribute.NativeAot.cs @@ -121,7 +121,7 @@ private static Attribute OneOrNull(IEnumerable results) return null; CustomAttributeData result = enumerator.Current; if (enumerator.MoveNext()) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(result); return result.Instantiate(); } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/QueryResult.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/QueryResult.cs index 301fe25f6fa389..6288b58c405217 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/QueryResult.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/BindingFlagSupport/QueryResult.cs @@ -112,11 +112,10 @@ public void CopyTo(MemberInfo[] array, int startIndex) // Assuming the policy says it's ok to ignore the ambiguity, we're to resolve in favor of the member // declared by the most derived type. Since QueriedMemberLists are sorted in order of decreasing derivation, // that means we let the first match win - unless, of course, they're both the "most derived member". - if (match.DeclaringType.Equals(challenger.DeclaringType)) - throw new AmbiguousMatchException(); - - if (!_policies.OkToIgnoreAmbiguity(match, challenger)) - throw new AmbiguousMatchException(); + // If they're not from same type, we throw if the policy doesn't allow ambiguity. + if (match.DeclaringType.Equals(challenger.DeclaringType) || + !_policies.OkToIgnoreAmbiguity(match, challenger)) + throw ThrowHelper.GetAmbiguousMatchException(match); } else { diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ThunkedApis.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ThunkedApis.cs index 3e0765205c6373..99858e0bbaa784 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ThunkedApis.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/General/ThunkedApis.cs @@ -199,7 +199,7 @@ public sealed override Type[] GetGenericArguments() if (ns != null && !ns.Equals(ifc.Namespace)) continue; if (match != null) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(match); match = ifc; } return match; diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeThinMethodParameterInfo.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeThinMethodParameterInfo.cs index b1c543238de156..a93368402a4bc2 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeThinMethodParameterInfo.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/ParameterInfos/RuntimeThinMethodParameterInfo.cs @@ -62,8 +62,7 @@ public sealed override bool HasDefaultValue { get { - // Compat: returning "true" makes no sense but this is how it's always been. - return true; + return false; } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs index dcb0ed3e093320..35ae4a96ea7c28 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Reflection/Runtime/TypeInfos/RuntimeTypeInfo.BindingFlags.cs @@ -155,9 +155,10 @@ protected sealed override PropertyInfo GetPropertyImpl(string name, BindingFlags if (types == null || types.Length == 0) { // no arguments + PropertyInfo firstCandidate = candidates[0]; + if (candidates.Count == 1) { - PropertyInfo firstCandidate = candidates[0]; if (returnType is not null && !returnType.IsEquivalentTo(firstCandidate.PropertyType)) return null; return firstCandidate; @@ -165,8 +166,10 @@ protected sealed override PropertyInfo GetPropertyImpl(string name, BindingFlags else { if (returnType is null) + { // if we are here we have no args or property type to select over and we have more than one property with that name - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(firstCandidate); + } } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Com.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Com.cs index 17e1bdb85ddfcb..1ac3410c8afa04 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Com.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Com.cs @@ -50,6 +50,7 @@ public static IntPtr CreateAggregatedObject(IntPtr pOuter, T o) where T : not [SupportedOSPlatform("windows")] [EditorBrowsable(EditorBrowsableState.Never)] + [return: NotNullIfNotNull(nameof(o))] public static object? CreateWrapperOfType(object? o, Type t) { throw new NotSupportedException(SR.PlatformNotSupported_ComInterop); diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs index 61f8c38b6cb93b..68b50d5bb966ee 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -351,9 +351,6 @@ internal static unsafe object IsInstanceOf(EETypePtr pTargetType, object obj) [RuntimeImport(RuntimeLibrary, "RhBoxAny")] internal static extern unsafe object RhBoxAny(ref byte pData, MethodTable* pEEType); - internal static unsafe object RhBoxAny(ref byte pData, EETypePtr pEEType) - => RhBoxAny(ref pData, pEEType.ToPointer()); - [MethodImpl(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhNewObject")] internal static extern unsafe object RhNewObject(MethodTable* pEEType); @@ -473,8 +470,6 @@ internal static unsafe int RhCompatibleReentrantWaitAny(bool alertable, int time [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhResolveDispatchOnType")] - // For my life cannot figure out the ordering of modifiers this is expecting. -#pragma warning disable IDE0036 internal static extern unsafe IntPtr RhResolveDispatchOnType(EETypePtr instanceType, EETypePtr interfaceType, ushort slot, EETypePtr* pGenericContext); internal static unsafe IntPtr RhResolveDispatchOnType(EETypePtr instanceType, EETypePtr interfaceType, ushort slot) @@ -554,16 +549,12 @@ internal static IntPtr RhGetModuleSection(TypeManagerHandle module, ReadyToRunSe internal static extern uint RhGetLoadedOSModules(IntPtr[] resultArray); [MethodImplAttribute(MethodImplOptions.InternalCall)] - [RuntimeImport(RuntimeLibrary, "RhGetOSModuleFromPointer")] - internal static extern IntPtr RhGetOSModuleFromPointer(IntPtr pointerVal); - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [RuntimeImport(RuntimeLibrary, "RhGetModuleFromEEType")] - internal static extern TypeManagerHandle RhGetModuleFromEEType(IntPtr pEEType); + [RuntimeImport(RuntimeLibrary, "RhGetKnobValues")] + internal static extern unsafe uint RhGetKnobValues(out byte** keyArray, out byte** valueArray); [MethodImplAttribute(MethodImplOptions.InternalCall)] - [RuntimeImport(RuntimeLibrary, "RhGetOSModuleFromEEType")] - internal static extern IntPtr RhGetOSModuleFromEEType(IntPtr pEEType); + [RuntimeImport(RuntimeLibrary, "RhGetOSModuleFromPointer")] + internal static extern IntPtr RhGetOSModuleFromPointer(IntPtr pointerVal); [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "RhGetThreadStaticStorage")] @@ -616,11 +607,6 @@ internal static IntPtr RhGetModuleSection(TypeManagerHandle module, ReadyToRunSe internal static extern unsafe int RhGetModuleFileName(IntPtr moduleHandle, out char* moduleName); #endif - // returns the previous value. - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [RuntimeImport(RuntimeLibrary, "RhSetErrorInfoBuffer")] - internal static extern unsafe void* RhSetErrorInfoBuffer(void* pNewBuffer); - // // StackTrace helper // @@ -645,21 +631,6 @@ internal static IntPtr RhGetModuleSection(TypeManagerHandle module, ReadyToRunSe [RuntimeImport(RuntimeLibrary, "RhSetThreadExitCallback")] internal static extern unsafe void RhSetThreadExitCallback(delegate* unmanaged pCallback); - // Functions involved in thunks from managed to managed functions (Universal transition transitions - // from an arbitrary method call into a defined function, and CallDescrWorker goes the other way. - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [RuntimeImport(RuntimeLibrary, "RhGetUniversalTransitionThunk")] - internal static extern IntPtr RhGetUniversalTransitionThunk(); - - // For Managed to Managed calls - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [RuntimeImport(RuntimeLibrary, "RhCallDescrWorker")] - internal static extern void RhCallDescrWorker(IntPtr callDescr); - - // For Managed to Native calls - [LibraryImport(RuntimeLibrary, EntryPoint = "RhCallDescrWorker")] - internal static partial void RhCallDescrWorkerNative(IntPtr callDescr); - // Moves memory from smem to dmem. Size must be a positive value. // This copy uses an intrinsic to be safe for copying arbitrary bits of // heap memory @@ -791,10 +762,6 @@ internal static unsafe partial void RhEventPipeInternal_WriteEventData( [RuntimeImport(RuntimeLibrary, "RhpCheckedXchg")] internal static extern object InterlockedExchange([NotNullIfNotNull(nameof(value))] ref object? location1, object? value); - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [RuntimeImport(RuntimeLibrary, "RhpMemoryBarrier")] - internal static extern void MemoryBarrier(); - [Intrinsic] [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "acos")] diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs index 3a9e422c9558e9..e9c15296ccd88f 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/RuntimeTypeHandle.cs @@ -16,10 +16,7 @@ namespace System [StructLayout(LayoutKind.Sequential)] public unsafe struct RuntimeTypeHandle : IEquatable, ISerializable { - // - // Caution: There can be and are multiple MethodTable for the "same" type (e.g. int[]). That means - // you can't use the raw IntPtr value for comparisons. - // + private IntPtr _value; internal RuntimeTypeHandle(EETypePtr pEEType) : this(pEEType.RawValue) @@ -123,7 +120,5 @@ internal bool IsNull return _value == new IntPtr(0); } } - - private IntPtr _value; } } diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Interlocked.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Interlocked.cs index 56f16cbcfbbe4c..f8a5e61ecbb65c 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Interlocked.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Threading/Interlocked.cs @@ -4,9 +4,6 @@ using System.Runtime; using System.Runtime.CompilerServices; using System.Diagnostics.CodeAnalysis; -using System.Runtime.Versioning; - -using Internal.Runtime.CompilerServices; namespace System.Threading { @@ -26,22 +23,6 @@ public static long CompareExchange(ref long location1, long value, long comparan return RuntimeImports.InterlockedCompareExchange(ref location1, value, comparand); } - [Intrinsic] - public static unsafe float CompareExchange(ref float location1, float value, float comparand) - { - float ret; - *(int*)&ret = CompareExchange(ref Unsafe.As(ref location1), *(int*)&value, *(int*)&comparand); - return ret; - } - - [Intrinsic] - public static unsafe double CompareExchange(ref double location1, double value, double comparand) - { - double ret; - *(long*)&ret = CompareExchange(ref Unsafe.As(ref location1), *(long*)&value, *(long*)&comparand); - return ret; - } - [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NotNullIfNotNull(nameof(location1))] @@ -87,22 +68,6 @@ public static long Exchange(ref long location1, long value) return oldValue; } - [Intrinsic] - public static unsafe float Exchange(ref float location1, float value) - { - float ret; - *(int*)&ret = Exchange(ref Unsafe.As(ref location1), *(int*)&value); - return ret; - } - - [Intrinsic] - public static unsafe double Exchange(ref double location1, double value) - { - double ret; - *(long*)&ret = Exchange(ref Unsafe.As(ref location1), *(long*)&value); - return ret; - } - [Intrinsic] [MethodImpl(MethodImplOptions.AggressiveInlining)] [return: NotNullIfNotNull(nameof(location1))] @@ -196,14 +161,6 @@ private static long ExchangeAdd(ref long location1, long value) #endregion - #region MemoryBarrier - [Intrinsic] - public static void MemoryBarrier() - { - RuntimeImports.MemoryBarrier(); - } - #endregion - #region Read public static long Read(ref long location) { diff --git a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs index 1da045804d9251..8f1a187c6fc0a0 100644 --- a/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs +++ b/src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs @@ -743,7 +743,7 @@ private static FunctionPointersToOffsets ComputeLdftnReverseLookup_InvokeMap(Nat continue; entryParser.SkipInteger(); // entryMethodHandleOrNameAndSigRaw - entryParser.SkipInteger(); // entryDeclaringTypeRaw + RuntimeTypeHandle declaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); IntPtr entryMethodEntrypoint = externalReferences.GetFunctionPointerFromIndex(entryParser.GetUnsigned()); functionPointers.Add(new FunctionPointerOffsetPair(entryMethodEntrypoint, parserOffset)); @@ -752,17 +752,21 @@ private static FunctionPointersToOffsets ComputeLdftnReverseLookup_InvokeMap(Nat // stack trace resolution - the reverse LdFtn lookup internally used by the reflection // method resolution will work off an IP address on the stack which is an address // within the actual method, not the stub. - IntPtr targetAddress = RuntimeAugments.GetCodeTarget(entryMethodEntrypoint); - if (targetAddress != IntPtr.Zero && targetAddress != entryMethodEntrypoint) + if (RuntimeAugments.IsValueType(declaringTypeHandle)) { - functionPointers.Add(new FunctionPointerOffsetPair(targetAddress, parserOffset)); - } - IntPtr targetAddress2; - if (TypeLoaderEnvironment.TryGetTargetOfUnboxingAndInstantiatingStub(entryMethodEntrypoint, out targetAddress2) && - targetAddress2 != entryMethodEntrypoint && - targetAddress2 != targetAddress) - { - functionPointers.Add(new FunctionPointerOffsetPair(targetAddress2, parserOffset)); + IntPtr targetAddress = RuntimeAugments.GetCodeTarget(entryMethodEntrypoint); + if (targetAddress != IntPtr.Zero && targetAddress != entryMethodEntrypoint) + { + functionPointers.Add(new FunctionPointerOffsetPair(targetAddress, parserOffset)); + } + + IntPtr targetAddress2; + if (TypeLoaderEnvironment.TryGetTargetOfUnboxingAndInstantiatingStub(entryMethodEntrypoint, out targetAddress2) && + targetAddress2 != entryMethodEntrypoint && + targetAddress2 != targetAddress) + { + functionPointers.Add(new FunctionPointerOffsetPair(targetAddress2, parserOffset)); + } } } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.cs b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.cs index dd3f3dac45b191..bd6c07a99e2651 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.cs +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Reflection/Execution/AssemblyBinderImplementation.cs @@ -84,7 +84,7 @@ public sealed override bool Bind(RuntimeAssemblyName refName, bool cacheMissedLo { if (foundMatch) { - exception = new AmbiguousMatchException(); + exception = new AmbiguousMatchException(SR.Format(SR.AmbiguousMatchException_Assembly, refName.FullName)); return false; } diff --git a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Resources/Strings.resx b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Resources/Strings.resx index 949e8adc2fbadc..cddf33a5bca989 100644 --- a/src/coreclr/nativeaot/System.Private.TypeLoader/src/Resources/Strings.resx +++ b/src/coreclr/nativeaot/System.Private.TypeLoader/src/Resources/Strings.resx @@ -1,17 +1,17 @@  - @@ -129,4 +129,7 @@ Cannot load assembly '{0}'. The assembly exists but its version {1} is lower than the requested version {2}. + + Ambiguous match found for assembly '{0}'. + diff --git a/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/RuntimeImports.cs index bd1681f250dfa6..5232ab073a6ca8 100644 --- a/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/coreclr/nativeaot/Test.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -103,10 +103,6 @@ internal static unsafe Array RhNewArray(EETypePtr pEEType, int length) [RuntimeImport(RuntimeLibrary, "RhpLockCmpXchg64")] internal static extern long InterlockedCompareExchange(ref long location1, long value, long comparand); - [MethodImplAttribute(MethodImplOptions.InternalCall)] - [RuntimeImport(RuntimeLibrary, "RhpMemoryBarrier")] - internal static extern void MemoryBarrier(); - // Moves memory from smem to dmem. Size must be a positive value. // This copy uses an intrinsic to be safe for copying arbitrary bits of // heap memory diff --git a/src/coreclr/nativeaot/Test.CoreLib/src/System/RuntimeTypeHandle.cs b/src/coreclr/nativeaot/Test.CoreLib/src/System/RuntimeTypeHandle.cs index d921e27015b73c..f0401dc09e07a9 100644 --- a/src/coreclr/nativeaot/Test.CoreLib/src/System/RuntimeTypeHandle.cs +++ b/src/coreclr/nativeaot/Test.CoreLib/src/System/RuntimeTypeHandle.cs @@ -10,17 +10,17 @@ namespace System [StructLayout(LayoutKind.Sequential)] public struct RuntimeTypeHandle { - private EETypePtr _pEEType; + private IntPtr _value; - internal RuntimeTypeHandle(EETypePtr pEEType) + internal RuntimeTypeHandle(IntPtr value) { - _pEEType = pEEType; + _value = value; } [Intrinsic] internal static unsafe IntPtr ToIntPtr(RuntimeTypeHandle handle) { - return (IntPtr)handle._pEEType.ToPointer(); + return handle._value; } } } @@ -32,7 +32,7 @@ internal static class LdTokenHelpers { private static RuntimeTypeHandle GetRuntimeTypeHandle(IntPtr pEEType) { - return new RuntimeTypeHandle(new EETypePtr(pEEType)); + return new RuntimeTypeHandle(pEEType); } } } diff --git a/src/coreclr/nativeaot/Test.CoreLib/src/System/Threading/Interlocked.cs b/src/coreclr/nativeaot/Test.CoreLib/src/System/Threading/Interlocked.cs index 34d02ffca1d6dc..58decc90318c1e 100644 --- a/src/coreclr/nativeaot/Test.CoreLib/src/System/Threading/Interlocked.cs +++ b/src/coreclr/nativeaot/Test.CoreLib/src/System/Threading/Interlocked.cs @@ -31,9 +31,6 @@ public static long CompareExchange(ref long location1, long value, long comparan } [Intrinsic] - public static void MemoryBarrier() - { - RuntimeImports.MemoryBarrier(); - } + public static void MemoryBarrier() => MemoryBarrier(); } } diff --git a/src/coreclr/nativeaot/docs/optimizing.md b/src/coreclr/nativeaot/docs/optimizing.md index 9f2c9ae70d12a8..9a90eb97c21286 100644 --- a/src/coreclr/nativeaot/docs/optimizing.md +++ b/src/coreclr/nativeaot/docs/optimizing.md @@ -40,4 +40,5 @@ Since `PublishTrimmed` is implied to be true with Native AOT, some framework fea * `Speed`: when generating optimized code, favor code execution speed. * `Size`: when generating optimized code, favor smaller code size. * ``: By default, the compiler targets the minimum instruction set supported by the target OS and architecture. This option allows targeting newer instruction sets for better performance. The native binary will require the instruction sets to be supported by the hardware in order to run. For example, `avx2,bmi2,fma,pclmul,popcnt,aes` will produce binary that takes advantage of instruction sets that are typically present on current Intel and AMD processors. Run `ilc --help` for the full list of available instruction sets. `ilc` can be executed from the NativeAOT package in your local nuget cache e.g. `%USERPROFILE%\.nuget\packages\runtime.win-x64.microsoft.dotnet.ilcompiler\8.0.0-...\tools\ilc.exe` on Windows or `~/.nuget/packages/runtime.linux-arm64.microsoft.dotnet.ilcompiler/8.0.0-.../tools/ilc` on Linux. +* ``: By default, the compiler targets the a `Vector` size of `16` or `32` bytes, depending on the underlying instruction sets supported. This option allows specifying a different maximum bit width. For example, if by default on x64 hardware `Vector` will be 16-bytes. However, if `AVX2` is targeted then `Vector` will automatically grow to be 32-bytes instead, setting `128` would keep the size as 16-bytes. Alternatively, even if `AVX512F` is targeted then by default `Vector` will not grow larger than 32-bytes, setting `512` would allow it to grow to 64-bytes. diff --git a/src/coreclr/pal/src/misc/jitsupport.cpp b/src/coreclr/pal/src/misc/jitsupport.cpp index f7ca5c36e71217..30426290043514 100644 --- a/src/coreclr/pal/src/misc/jitsupport.cpp +++ b/src/coreclr/pal/src/misc/jitsupport.cpp @@ -235,7 +235,10 @@ PAL_GetJitCpuCapabilityFlags(CORJIT_FLAGS *flags) #endif #ifdef HWCAP_ASIMD if (hwCap & HWCAP_ASIMD) + { flags->Set(InstructionSet_AdvSimd); + flags->Set(InstructionSet_VectorT128); + } #endif #ifdef HWCAP_ASIMDRDM if (hwCap & HWCAP_ASIMDRDM) @@ -292,6 +295,7 @@ PAL_GetJitCpuCapabilityFlags(CORJIT_FLAGS *flags) // Set baseline flags if OS has not exposed mechanism for us to determine CPU capabilities flags->Set(InstructionSet_ArmBase); flags->Set(InstructionSet_AdvSimd); + flags->Set(InstructionSet_VectorT128); // flags->Set(CORJIT_FLAGS::CORJIT_FLAG_HAS_ARM64_FP); #endif // HAVE_AUXV_HWCAP_H } diff --git a/src/coreclr/scripts/superpmi-collect.proj b/src/coreclr/scripts/superpmi-collect.proj index a7a465b4639bb2..490836a21cc014 100644 --- a/src/coreclr/scripts/superpmi-collect.proj +++ b/src/coreclr/scripts/superpmi-collect.proj @@ -72,19 +72,19 @@ - + %HELIX_WORKITEM_PAYLOAD%\binaries - + $HELIX_WORKITEM_PAYLOAD/binaries - + %HELIX_WORKITEM_PAYLOAD%\performance - + $HELIX_WORKITEM_PAYLOAD/performance @@ -130,12 +130,12 @@ - + $(Python) $(SuperPMIDirectory)$(FileSeparatorChar)superpmi.py collect --clean -log_level DEBUG --$(CollectionType) $(PmiArguments) -assemblies $(AssembliesDirectoryOnHelix) -arch $(Architecture) -build_type $(BuildConfig) -core_root $(SuperPMIDirectory) 2:00 - + $(Python) $(SuperPMIDirectory)$(FileSeparatorChar)superpmi_benchmarks.py -performance_directory $(PerformanceDirectory) -superpmi_directory $(SuperPMIDirectory) -core_root $(SuperPMIDirectory) -arch $(Architecture) $(RunArguments) 3:00 @@ -174,7 +174,7 @@ - + @@ -182,8 +182,15 @@ - + 30 + src\benchmarks\micro\MicroBenchmarks.csproj + MicroBenchmarks.dll + + + 30 + src/benchmarks/micro/MicroBenchmarks.csproj + MicroBenchmarks.dll @@ -217,8 +224,24 @@ - - + + + + + + + + + + + + + + + + + + $(CollectionName).$(CollectionType).%(HelixWorkItem.PartitionId).$(MchFileTag) $(AssembliesPayload)$(FileSeparatorChar)%(HelixWorkItem.CollectAssemblies) @@ -232,9 +255,19 @@ $(CollectionName).$(CollectionType).%(HelixWorkItem.Index).$(MchFileTag) $(WorkItemDirectory) - $(WorkItemCommand) -partition_count $(PartitionCount) -partition_index %(HelixWorkItem.Index) -output_mch_path $(OutputMchPath)$(FileSeparatorChar)%(OutputFileName).mch -log_file $(OutputMchPath)$(FileSeparatorChar)%(OutputFileName).log + $(WorkItemCommand) -partition_count $(PartitionCount) -partition_index %(HelixWorkItem.Index) -benchmark_path $(BenchmarkPath) -benchmark_binary $(BenchmarkBinary) -output_mch_path $(OutputMchPath)$(FileSeparatorChar)%(OutputFileName).mch -log_file $(OutputMchPath)$(FileSeparatorChar)%(OutputFileName).log $(WorkItemTimeout) %(OutputFileName).mch;%(OutputFileName).mch.mct;%(OutputFileName).log + + + + $(CollectionName).$(CollectionType).%(HelixWorkItem.Index).$(MchFileTag) + $(WorkItemDirectory) + $(WorkItemCommand) -partition_count 1 -partition_index 0 -benchmark_path %(HelixWorkItem.BenchmarkPath) -benchmark_binary %(HelixWorkItem.BenchmarkBinary) -output_mch_path $(OutputMchPath)$(FileSeparatorChar)%(OutputFileName).mch -log_file $(OutputMchPath)$(FileSeparatorChar)%(OutputFileName).log + $(WorkItemTimeout) + %(OutputFileName).mch;%(OutputFileName).mch.mct;%(OutputFileName).log + + diff --git a/src/coreclr/scripts/superpmi_benchmarks.py b/src/coreclr/scripts/superpmi_benchmarks.py index 7a09f47c8fd198..8b78a0099c4ddc 100644 --- a/src/coreclr/scripts/superpmi_benchmarks.py +++ b/src/coreclr/scripts/superpmi_benchmarks.py @@ -8,8 +8,9 @@ # # Notes: # -# Script to perform the superpmi collection while executing the Microbenchmarks present -# in https://github.com/dotnet/performance/tree/master/src/benchmarks/micro. +# Script to perform the superpmi collection while executing the Microbenchmarks in +# https://github.com/dotnet/performance/tree/master/src/benchmarks/micro and real-world in +# in https://github.com/dotnet/performance/tree/master/src/benchmarks/real-world import argparse import re @@ -34,6 +35,8 @@ parser.add_argument("-partition_count", help="Total number of partitions") parser.add_argument("-partition_index", help="Partition index to do the collection for") parser.add_argument("-arch", help="Architecture") +parser.add_argument("-benchmark_path", help="Benchmark's csproj path in dotnet/performance repo") +parser.add_argument("-benchmark_binary", help="Benchmark binary to execute") parser.add_argument("--tiered_compilation", action="store_true", help="Sets DOTNET_TieredCompilation=1 when doing collections.") parser.add_argument("--tiered_pgo", action="store_true", help="Sets DOTNET_TieredCompilation=1 and DOTNET_TieredPGO=1 when doing collections.") @@ -90,6 +93,16 @@ def setup_args(args): lambda arch: arch.lower() in ["x86", "x64", "arm", "arm64"], "Unable to set arch") + coreclr_args.verify(args, + "benchmark_path", + lambda unused: True, + "Unable to set benchmark_path") + + coreclr_args.verify(args, + "benchmark_binary", + lambda unused: True, + "Unable to set benchmark_binary") + coreclr_args.verify(args, "tiered_compilation", lambda unused: True, @@ -123,9 +136,8 @@ def make_executable(file_name): (stat.S_IROTH | stat.S_IXOTH)) run_command(["ls", "-l", file_name]) - def build_and_run(coreclr_args, output_mch_name): - """Build the microbenchmarks and run them under "superpmi collect" + """Build the microbenchmarks/real-world and run them under "superpmi collect" Args: coreclr_args (CoreClrArguments): Arguments use to drive @@ -139,13 +151,15 @@ def build_and_run(coreclr_args, output_mch_name): log_file = coreclr_args.log_file partition_count = coreclr_args.partition_count partition_index = coreclr_args.partition_index + benchmark_path = coreclr_args.benchmark_path + benchmark_binary = coreclr_args.benchmark_binary dotnet_directory = os.path.join(performance_directory, "tools", "dotnet", arch) dotnet_exe = os.path.join(dotnet_directory, "dotnet") artifacts_directory = os.path.join(performance_directory, "artifacts") artifacts_packages_directory = os.path.join(artifacts_directory, "packages") - project_file = os.path.join(performance_directory, "src", "benchmarks", "micro", "MicroBenchmarks.csproj") - benchmarks_dll = os.path.join(artifacts_directory, "MicroBenchmarks.dll") + project_file = os.path.join(performance_directory, benchmark_path) + benchmarks_dll = os.path.join(artifacts_directory, benchmark_binary) # Workaround https://github.com/dotnet/sdk/issues/23430 project_file = os.path.realpath(project_file) @@ -153,11 +167,11 @@ def build_and_run(coreclr_args, output_mch_name): if is_windows: shim_name = "%JitName%" corerun_exe = "CoreRun.exe" - script_name = "run_microbenchmarks.bat" + script_name = "run_benchmarks.bat" else: shim_name = "$JitName" corerun_exe = "corerun" - script_name = "run_microbenchmarks.sh" + script_name = "run_benchmarks.sh" make_executable(dotnet_exe) @@ -192,11 +206,25 @@ def build_and_run(coreclr_args, output_mch_name): "--framework", "net8.0", "--no-restore", "/p:NuGetPackageRoot=" + artifacts_packages_directory, "-o", artifacts_directory], _exit_on_fail=True) - # Disable ReadyToRun so we always JIT R2R methods and collect them - collection_command = f"{dotnet_exe} {benchmarks_dll} --filter \"*\" --corerun {os.path.join(core_root, corerun_exe)} --partition-count {partition_count} " \ - f"--partition-index {partition_index} --envVars DOTNET_JitName:{shim_name} " \ - " DOTNET_ZapDisable:1 DOTNET_ReadyToRun:0 " \ - "--iterationCount 1 --warmupCount 0 --invocationCount 1 --unrollFactor 1 --strategy ColdStart --logBuildOutput" + if benchmark_binary.lower().startswith("microbenchmarks"): + # Disable ReadyToRun so we always JIT R2R methods and collect them + collection_command = f"{dotnet_exe} {benchmarks_dll} --filter \"*\" --corerun {os.path.join(core_root, corerun_exe)} --partition-count {partition_count} " \ + f"--partition-index {partition_index} --envVars DOTNET_JitName:{shim_name} " \ + " DOTNET_ZapDisable:1 DOTNET_ReadyToRun:0 " \ + "--iterationCount 1 --warmupCount 0 --invocationCount 1 --unrollFactor 1 --strategy ColdStart --logBuildOutput" + elif benchmark_binary.lower().startswith("demobenchmarks"): + # Disable ReadyToRun so we always JIT R2R methods and collect them + collection_command = f"{dotnet_exe} {benchmarks_dll} -f *CollisionBatcherTaskBenchmarks.* *GroupedCollisionTesterBenchmarks.* *GatherScatterBenchmarks.* " \ + " *OneBodyConstraintBenchmarks.* *TwoBodyConstraintBenchmarks.* *ThreeBodyConstraintBenchmarks.* *FourBodyConstraintBenchmarks.* " \ + " *SweepBenchmarks.* *ShapeRayBenchmarks.* *ShapePileBenchmark.* *RagdollTubeBenchmark.* " \ + f" --corerun {os.path.join(core_root, corerun_exe)} --envVars DOTNET_JitName:{shim_name} " \ + " DOTNET_ZapDisable:1 DOTNET_ReadyToRun:0 " \ + "--iterationCount 1 --warmupCount 0 --invocationCount 1 --unrollFactor 1 --strategy ColdStart --logBuildOutput" + else: + # Disable ReadyToRun so we always JIT R2R methods and collect them + collection_command = f"{dotnet_exe} {benchmarks_dll} --filter \"*\" --corerun {os.path.join(core_root, corerun_exe)} --envVars DOTNET_JitName:{shim_name} " \ + " DOTNET_ZapDisable:1 DOTNET_ReadyToRun:0 " \ + "--iterationCount 1 --warmupCount 0 --invocationCount 1 --unrollFactor 1 --strategy ColdStart --logBuildOutput" # Generate the execution script in Temp location with TempDir() as temp_location: diff --git a/src/coreclr/scripts/superpmi_collect_setup.py b/src/coreclr/scripts/superpmi_collect_setup.py index 84240c90418f73..f93cd287e15161 100644 --- a/src/coreclr/scripts/superpmi_collect_setup.py +++ b/src/coreclr/scripts/superpmi_collect_setup.py @@ -376,8 +376,8 @@ def partition_files(src_directory, dst_directory, max_size, exclude_directories= index += 1 -def setup_microbenchmark(workitem_directory, arch): - """ Perform setup of microbenchmarks +def setup_benchmark(workitem_directory, arch): + """ Perform setup of microbenchmarks/realworld Args: workitem_directory (string): Path to work @@ -485,9 +485,9 @@ def main(main_args): print('Copying {} -> {}'.format(coreclr_args.core_root_directory, core_root_dst_directory)) copy_directory(coreclr_args.core_root_directory, core_root_dst_directory, verbose_output=True, match_func=acceptable_copy) - if coreclr_args.collection_name == "benchmarks": - # Setup microbenchmarks - setup_microbenchmark(workitem_payload_directory, arch) + if coreclr_args.collection_name == "benchmarks" or coreclr_args.collection_name == "realworld": + # Setup benchmarks + setup_benchmark(workitem_payload_directory, arch) else: # Setup for pmi/crossgen2 runs diff --git a/src/coreclr/scripts/superpmi_diffs_setup.py b/src/coreclr/scripts/superpmi_diffs_setup.py index db12452de8d86e..c54de696ccd972 100644 --- a/src/coreclr/scripts/superpmi_diffs_setup.py +++ b/src/coreclr/scripts/superpmi_diffs_setup.py @@ -171,7 +171,6 @@ def build_jit_analyze(coreclr_args, source_directory, jit_analyze_build_director # The RID catalog is here: https://docs.microsoft.com/en-us/dotnet/core/rid-catalog. # Windows x64 => win-x64 # Windows x86 => win-x86 - # Windows arm32 => win-arm # Windows arm64 => win-arm64 # Linux x64 => linux-x64 # Linux arm32 => linux-arm diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/EmbeddedDataContainerNode.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/EmbeddedDataContainerNode.cs index 3aa40631fb3fae..a43b776bddc929 100644 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/EmbeddedDataContainerNode.cs +++ b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/EmbeddedDataContainerNode.cs @@ -1,33 +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 Internal.Text; + namespace ILCompiler.DependencyAnalysis { /// /// Represents a node that contains a set of embedded objects. The main function is /// to serve as a base class, providing symbol name boundaries and node ordering. /// - public abstract class EmbeddedDataContainerNode : ObjectNode + public abstract class EmbeddedDataContainerNode : ObjectNode, ISymbolDefinitionNode { - private ObjectAndOffsetSymbolNode _startSymbol; - private ObjectAndOffsetSymbolNode _endSymbol; - private string _startSymbolMangledName; - - public ObjectAndOffsetSymbolNode StartSymbol => _startSymbol; - public ObjectAndOffsetSymbolNode EndSymbol => _endSymbol; + private string _mangledName; - protected EmbeddedDataContainerNode(string startSymbolMangledName, string endSymbolMangledName) + protected EmbeddedDataContainerNode(string mangledName) { - _startSymbolMangledName = startSymbolMangledName; - _startSymbol = new ObjectAndOffsetSymbolNode(this, 0, startSymbolMangledName, true); - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, endSymbolMangledName, true); + _mangledName = mangledName; } + public int Offset => 0; + public override int ClassCode => -1410622237; + public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) + => sb.Append(nameMangler.CompilationUnitPrefix).Append(_mangledName); + public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) { - return _startSymbolMangledName.CompareTo(((EmbeddedDataContainerNode)other)._startSymbolMangledName); + return _mangledName.CompareTo(((EmbeddedDataContainerNode)other)._mangledName); } } } diff --git a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectAndOffsetSymbolNode.cs b/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectAndOffsetSymbolNode.cs deleted file mode 100644 index 0f15706ea685c8..00000000000000 --- a/src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectAndOffsetSymbolNode.cs +++ /dev/null @@ -1,60 +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 ILCompiler.DependencyAnalysisFramework; - -using Internal.Text; - -namespace ILCompiler.DependencyAnalysis -{ - public class ObjectAndOffsetSymbolNode : DependencyNodeCore, ISymbolDefinitionNode - { - private ObjectNode _object; - private int _offset; - private Utf8String _name; - private bool _includeCompilationUnitPrefix; - - public ObjectAndOffsetSymbolNode(ObjectNode obj, int offset, Utf8String name, bool includeCompilationUnitPrefix) - { - _object = obj; - _offset = offset; - _name = name; - _includeCompilationUnitPrefix = includeCompilationUnitPrefix; - } - - protected override string GetName(NodeFactory factory) => $"Symbol {_name} at offset {_offset.ToStringInvariant()}"; - - public override bool HasConditionalStaticDependencies => false; - public override bool HasDynamicDependencies => false; - public override bool InterestingForDynamicDependencyAnalysis => false; - public override bool StaticDependenciesAreComputed => true; - - public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) - { - if (_includeCompilationUnitPrefix) - sb.Append(nameMangler.CompilationUnitPrefix); - sb.Append(_name); - } - - int ISymbolNode.Offset => 0; - int ISymbolDefinitionNode.Offset => _offset; - public bool RepresentsIndirectionCell => false; - - public void SetSymbolOffset(int offset) - { - _offset = offset; - } - - public ObjectNode Target => _object; - - public override IEnumerable GetStaticDependencies(NodeFactory factory) - { - return new DependencyListEntry[] { new DependencyListEntry(_object, "ObjectAndOffsetDependency") }; - } - - public override IEnumerable GetConditionalStaticDependencies(NodeFactory factory) => null; - public override IEnumerable SearchDynamicDependencies(List> markedNodes, int firstNode, NodeFactory factory) => null; - } -} diff --git a/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs b/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs index 6d124bda4673c6..46528387fec8ca 100644 --- a/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs +++ b/src/coreclr/tools/Common/Compiler/InstructionSetSupport.cs @@ -96,18 +96,37 @@ public SimdVectorLength GetVectorTSimdVector() { if ((_targetArchitecture == TargetArchitecture.X64) || (_targetArchitecture == TargetArchitecture.X86)) { - Debug.Assert(InstructionSet.X64_AVX2 == InstructionSet.X86_AVX2); - Debug.Assert(InstructionSet.X64_SSE2 == InstructionSet.X86_SSE2); - if (IsInstructionSetSupported(InstructionSet.X86_AVX2)) + Debug.Assert(InstructionSet.X64_VectorT128 == InstructionSet.X86_VectorT128); + Debug.Assert(InstructionSet.X64_VectorT256 == InstructionSet.X86_VectorT256); + Debug.Assert(InstructionSet.X64_VectorT512 == InstructionSet.X86_VectorT512); + + // TODO-XArch: Add support for 512-bit Vector + Debug.Assert(!IsInstructionSetSupported(InstructionSet.X64_VectorT512)); + + if (IsInstructionSetSupported(InstructionSet.X64_VectorT256)) + { + Debug.Assert(!IsInstructionSetSupported(InstructionSet.X64_VectorT128)); return SimdVectorLength.Vector256Bit; - else if (IsInstructionSetExplicitlyUnsupported(InstructionSet.X86_AVX2) && IsInstructionSetSupported(InstructionSet.X64_SSE2)) + } + else if (IsInstructionSetSupported(InstructionSet.X64_VectorT128)) + { return SimdVectorLength.Vector128Bit; + } else + { return SimdVectorLength.None; + } } else if (_targetArchitecture == TargetArchitecture.ARM64) { - return SimdVectorLength.Vector128Bit; + if (IsInstructionSetSupported(InstructionSet.ARM64_VectorT128)) + { + return SimdVectorLength.Vector128Bit; + } + else + { + return SimdVectorLength.None; + } } else if (_targetArchitecture == TargetArchitecture.ARM) { @@ -183,15 +202,24 @@ public static InstructionSetFlags GetNonSpecifiableInstructionSetsForArch(Target return s_nonSpecifiableInstructionSets[architecture]; } - private readonly SortedSet _supportedInstructionSets = new SortedSet(); - private readonly SortedSet _unsupportedInstructionSets = new SortedSet(); + private readonly SortedSet _supportedInstructionSets; + private readonly SortedSet _unsupportedInstructionSets; private readonly TargetArchitecture _architecture; public InstructionSetSupportBuilder(TargetArchitecture architecture) { + _supportedInstructionSets = new SortedSet(); + _unsupportedInstructionSets = new SortedSet(); _architecture = architecture; } + public InstructionSetSupportBuilder(InstructionSetSupportBuilder other) + { + _supportedInstructionSets = new SortedSet(other._supportedInstructionSets); + _unsupportedInstructionSets = new SortedSet(other._unsupportedInstructionSets); + _architecture = other._architecture; + } + /// /// Add a supported instruction set to the specified list. /// @@ -245,9 +273,10 @@ public bool RemoveInstructionSetSupport(string instructionSet) /// Seal modifications to instruction set support /// /// returns "false" if instruction set isn't valid on this architecture - public bool ComputeInstructionSetFlags(out InstructionSetFlags supportedInstructionSets, - out InstructionSetFlags unsupportedInstructionSets, - Action invalidInstructionSetImplication) + public bool ComputeInstructionSetFlags(int maxVectorTBitWidth, + out InstructionSetFlags supportedInstructionSets, + out InstructionSetFlags unsupportedInstructionSets, + Action invalidInstructionSetImplication) { supportedInstructionSets = new InstructionSetFlags(); unsupportedInstructionSets = new InstructionSetFlags(); @@ -288,6 +317,51 @@ public bool ComputeInstructionSetFlags(out InstructionSetFlags supportedInstruct } } + switch (_architecture) + { + case TargetArchitecture.X64: + case TargetArchitecture.X86: + { + Debug.Assert(InstructionSet.X86_SSE2 == InstructionSet.X64_SSE2); + Debug.Assert(InstructionSet.X86_AVX2 == InstructionSet.X64_AVX2); + Debug.Assert(InstructionSet.X86_AVX512F == InstructionSet.X64_AVX512F); + + Debug.Assert(InstructionSet.X86_VectorT128 == InstructionSet.X64_VectorT128); + Debug.Assert(InstructionSet.X86_VectorT256 == InstructionSet.X64_VectorT256); + Debug.Assert(InstructionSet.X86_VectorT512 == InstructionSet.X64_VectorT512); + + // We only want one size supported for Vector and we want the other sizes explicitly + // unsupported to ensure we throw away the given methods if runtime picks a larger size + + Debug.Assert(supportedInstructionSets.HasInstructionSet(InstructionSet.X86_SSE2)); + Debug.Assert((maxVectorTBitWidth == 0) || (maxVectorTBitWidth >= 128)); + supportedInstructionSets.AddInstructionSet(InstructionSet.X86_VectorT128); + + if (supportedInstructionSets.HasInstructionSet(InstructionSet.X86_AVX2)) + { + if ((maxVectorTBitWidth == 0) || (maxVectorTBitWidth >= 256)) + { + supportedInstructionSets.RemoveInstructionSet(InstructionSet.X86_VectorT128); + supportedInstructionSets.AddInstructionSet(InstructionSet.X86_VectorT256); + + unsupportedInstructionSets.AddInstructionSet(InstructionSet.X86_VectorT128); + unsupportedInstructionSets.AddInstructionSet(InstructionSet.X86_VectorT512); + } + + // TODO-XArch: Add support for 512-bit Vector + } + break; + } + + case TargetArchitecture.ARM64: + { + Debug.Assert(supportedInstructionSets.HasInstructionSet(InstructionSet.ARM64_AdvSimd)); + Debug.Assert((maxVectorTBitWidth == 0) || (maxVectorTBitWidth >= 128)); + supportedInstructionSets.AddInstructionSet(InstructionSet.ARM64_VectorT128); + break; + } + } + return true; } } diff --git a/src/coreclr/tools/Common/InstructionSetHelpers.cs b/src/coreclr/tools/Common/InstructionSetHelpers.cs index 8aa5705916dede..c969927e1531f7 100644 --- a/src/coreclr/tools/Common/InstructionSetHelpers.cs +++ b/src/coreclr/tools/Common/InstructionSetHelpers.cs @@ -11,7 +11,7 @@ namespace System.CommandLine { internal static partial class Helpers { - public static InstructionSetSupport ConfigureInstructionSetSupport(string instructionSet, TargetArchitecture targetArchitecture, TargetOS targetOS, + public static InstructionSetSupport ConfigureInstructionSetSupport(string instructionSet, int maxVectorTBitWidth, TargetArchitecture targetArchitecture, TargetOS targetOS, string mustNotBeMessage, string invalidImplicationMessage) { InstructionSetSupportBuilder instructionSetSupportBuilder = new(targetArchitecture); @@ -74,11 +74,16 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru } } - instructionSetSupportBuilder.ComputeInstructionSetFlags(out var supportedInstructionSet, out var unsupportedInstructionSet, + instructionSetSupportBuilder.ComputeInstructionSetFlags(maxVectorTBitWidth, out var supportedInstructionSet, out var unsupportedInstructionSet, (string specifiedInstructionSet, string impliedInstructionSet) => throw new CommandLineException(string.Format(invalidImplicationMessage, specifiedInstructionSet, impliedInstructionSet))); - InstructionSetSupportBuilder optimisticInstructionSetSupportBuilder = new InstructionSetSupportBuilder(targetArchitecture); + // Due to expansion by implication, the optimistic set is most often a pure superset of the supported set + // + // However, there are some gaps in cases like Arm64 neon where none of the optimistic sets imply it. Likewise, + // the optimistic set would be missing the explicitly unsupported sets. So we effectively clone the list and + // tack on the additional optimistic bits after. This ensures the optimistic set remains an accurate superset + InstructionSetSupportBuilder optimisticInstructionSetSupportBuilder = new InstructionSetSupportBuilder(instructionSetSupportBuilder); // Optimistically assume some instruction sets are present. if (targetArchitecture == TargetArchitecture.X86 || targetArchitecture == TargetArchitecture.X64) @@ -93,15 +98,38 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("movbe"); optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("popcnt"); optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("lzcnt"); + optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("serialize"); // If AVX was enabled, we can opportunistically enable instruction sets which use the VEX encodings Debug.Assert(InstructionSet.X64_AVX == InstructionSet.X86_AVX); if (supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX)) { + // TODO: Enable optimistic usage of AVX2 once we validate it doesn't break Vector usage + // optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("avx2"); + + if (supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX2)) + { + optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("avxvnni"); + } + optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("fma"); optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("bmi"); optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("bmi2"); - optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("avxvnni"); + } + + Debug.Assert(InstructionSet.X64_AVX512F == InstructionSet.X86_AVX512F); + if (supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX512F)) + { + Debug.Assert(supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX512F_VL)); + Debug.Assert(supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX512BW)); + Debug.Assert(supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX512BW_VL)); + Debug.Assert(supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX512CD)); + Debug.Assert(supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX512CD_VL)); + Debug.Assert(supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX512DQ)); + Debug.Assert(supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX512DQ_VL)); + + optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("avx512vbmi"); + optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("avx512vbmi_vl"); } } else if (targetArchitecture == TargetArchitecture.ARM64) @@ -111,9 +139,12 @@ public static InstructionSetSupport ConfigureInstructionSetSupport(string instru optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("sha1"); optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("sha2"); optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("lse"); + optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("dotprod"); + optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("rdma"); + optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("rcpc"); } - optimisticInstructionSetSupportBuilder.ComputeInstructionSetFlags(out var optimisticInstructionSet, out _, + optimisticInstructionSetSupportBuilder.ComputeInstructionSetFlags(maxVectorTBitWidth, out var optimisticInstructionSet, out _, (string specifiedInstructionSet, string impliedInstructionSet) => throw new NotSupportedException()); optimisticInstructionSet.Remove(unsupportedInstructionSet); optimisticInstructionSet.Add(supportedInstructionSet); diff --git a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSet.cs b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSet.cs index 0068f0be007764..32b60ecbcda7da 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSet.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSet.cs @@ -50,6 +50,9 @@ public enum ReadyToRunInstructionSet Avx512DQ_VL=36, Avx512Vbmi=37, Avx512Vbmi_VL=38, + VectorT128=39, + VectorT256=40, + VectorT512=41, } } diff --git a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSetHelper.cs b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSetHelper.cs index b387eedd89f2b7..f593808be32989 100644 --- a/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSetHelper.cs +++ b/src/coreclr/tools/Common/Internal/Runtime/ReadyToRunInstructionSetHelper.cs @@ -44,6 +44,7 @@ public static class ReadyToRunInstructionSetHelper case InstructionSet.ARM64_Vector128: return null; case InstructionSet.ARM64_Dczva: return null; case InstructionSet.ARM64_Rcpc: return ReadyToRunInstructionSet.Rcpc; + case InstructionSet.ARM64_VectorT128: return ReadyToRunInstructionSet.VectorT128; default: throw new Exception("Unknown instruction set"); } @@ -114,6 +115,9 @@ public static class ReadyToRunInstructionSetHelper case InstructionSet.X64_AVX512VBMI_X64: return ReadyToRunInstructionSet.Avx512Vbmi; case InstructionSet.X64_AVX512VBMI_VL: return ReadyToRunInstructionSet.Avx512Vbmi_VL; case InstructionSet.X64_AVX512VBMI_VL_X64: return ReadyToRunInstructionSet.Avx512Vbmi_VL; + case InstructionSet.X64_VectorT128: return ReadyToRunInstructionSet.VectorT128; + case InstructionSet.X64_VectorT256: return ReadyToRunInstructionSet.VectorT256; + case InstructionSet.X64_VectorT512: return ReadyToRunInstructionSet.VectorT512; default: throw new Exception("Unknown instruction set"); } @@ -184,6 +188,9 @@ public static class ReadyToRunInstructionSetHelper case InstructionSet.X86_AVX512VBMI_X64: return null; case InstructionSet.X86_AVX512VBMI_VL: return ReadyToRunInstructionSet.Avx512Vbmi_VL; case InstructionSet.X86_AVX512VBMI_VL_X64: return null; + case InstructionSet.X86_VectorT128: return ReadyToRunInstructionSet.VectorT128; + case InstructionSet.X86_VectorT256: return ReadyToRunInstructionSet.VectorT256; + case InstructionSet.X86_VectorT512: return ReadyToRunInstructionSet.VectorT512; default: throw new Exception("Unknown instruction set"); } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoInstructionSet.cs b/src/coreclr/tools/Common/JitInterface/CorInfoInstructionSet.cs index df6c06206bf84d..f26abd68262391 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoInstructionSet.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoInstructionSet.cs @@ -15,7 +15,7 @@ namespace Internal.JitInterface public enum InstructionSet { ILLEGAL = 0, - NONE = 63, + NONE = 127, ARM64_ArmBase = InstructionSet_ARM64.ArmBase, ARM64_AdvSimd = InstructionSet_ARM64.AdvSimd, ARM64_Aes = InstructionSet_ARM64.Aes, @@ -29,6 +29,7 @@ public enum InstructionSet ARM64_Vector128 = InstructionSet_ARM64.Vector128, ARM64_Dczva = InstructionSet_ARM64.Dczva, ARM64_Rcpc = InstructionSet_ARM64.Rcpc, + ARM64_VectorT128 = InstructionSet_ARM64.VectorT128, ARM64_ArmBase_Arm64 = InstructionSet_ARM64.ArmBase_Arm64, ARM64_AdvSimd_Arm64 = InstructionSet_ARM64.AdvSimd_Arm64, ARM64_Aes_Arm64 = InstructionSet_ARM64.Aes_Arm64, @@ -69,6 +70,9 @@ public enum InstructionSet X64_AVX512DQ_VL = InstructionSet_X64.AVX512DQ_VL, X64_AVX512VBMI = InstructionSet_X64.AVX512VBMI, X64_AVX512VBMI_VL = InstructionSet_X64.AVX512VBMI_VL, + X64_VectorT128 = InstructionSet_X64.VectorT128, + X64_VectorT256 = InstructionSet_X64.VectorT256, + X64_VectorT512 = InstructionSet_X64.VectorT512, X64_X86Base_X64 = InstructionSet_X64.X86Base_X64, X64_SSE_X64 = InstructionSet_X64.SSE_X64, X64_SSE2_X64 = InstructionSet_X64.SSE2_X64, @@ -130,6 +134,9 @@ public enum InstructionSet X86_AVX512DQ_VL = InstructionSet_X86.AVX512DQ_VL, X86_AVX512VBMI = InstructionSet_X86.AVX512VBMI, X86_AVX512VBMI_VL = InstructionSet_X86.AVX512VBMI_VL, + X86_VectorT128 = InstructionSet_X86.VectorT128, + X86_VectorT256 = InstructionSet_X86.VectorT256, + X86_VectorT512 = InstructionSet_X86.VectorT512, X86_X86Base_X64 = InstructionSet_X86.X86Base_X64, X86_SSE_X64 = InstructionSet_X86.SSE_X64, X86_SSE2_X64 = InstructionSet_X86.SSE2_X64, @@ -177,14 +184,15 @@ public enum InstructionSet_ARM64 Vector128 = 11, Dczva = 12, Rcpc = 13, - ArmBase_Arm64 = 14, - AdvSimd_Arm64 = 15, - Aes_Arm64 = 16, - Crc32_Arm64 = 17, - Dp_Arm64 = 18, - Rdm_Arm64 = 19, - Sha1_Arm64 = 20, - Sha256_Arm64 = 21, + VectorT128 = 14, + ArmBase_Arm64 = 15, + AdvSimd_Arm64 = 16, + Aes_Arm64 = 17, + Crc32_Arm64 = 18, + Dp_Arm64 = 19, + Rdm_Arm64 = 20, + Sha1_Arm64 = 21, + Sha256_Arm64 = 22, } public enum InstructionSet_X64 @@ -223,35 +231,38 @@ public enum InstructionSet_X64 AVX512DQ_VL = 30, AVX512VBMI = 31, AVX512VBMI_VL = 32, - X86Base_X64 = 33, - SSE_X64 = 34, - SSE2_X64 = 35, - SSE3_X64 = 36, - SSSE3_X64 = 37, - SSE41_X64 = 38, - SSE42_X64 = 39, - AVX_X64 = 40, - AVX2_X64 = 41, - AES_X64 = 42, - BMI1_X64 = 43, - BMI2_X64 = 44, - FMA_X64 = 45, - LZCNT_X64 = 46, - PCLMULQDQ_X64 = 47, - POPCNT_X64 = 48, - AVXVNNI_X64 = 49, - MOVBE_X64 = 50, - X86Serialize_X64 = 51, - AVX512F_X64 = 52, - AVX512F_VL_X64 = 53, - AVX512BW_X64 = 54, - AVX512BW_VL_X64 = 55, - AVX512CD_X64 = 56, - AVX512CD_VL_X64 = 57, - AVX512DQ_X64 = 58, - AVX512DQ_VL_X64 = 59, - AVX512VBMI_X64 = 60, - AVX512VBMI_VL_X64 = 61, + VectorT128 = 33, + VectorT256 = 34, + VectorT512 = 35, + X86Base_X64 = 36, + SSE_X64 = 37, + SSE2_X64 = 38, + SSE3_X64 = 39, + SSSE3_X64 = 40, + SSE41_X64 = 41, + SSE42_X64 = 42, + AVX_X64 = 43, + AVX2_X64 = 44, + AES_X64 = 45, + BMI1_X64 = 46, + BMI2_X64 = 47, + FMA_X64 = 48, + LZCNT_X64 = 49, + PCLMULQDQ_X64 = 50, + POPCNT_X64 = 51, + AVXVNNI_X64 = 52, + MOVBE_X64 = 53, + X86Serialize_X64 = 54, + AVX512F_X64 = 55, + AVX512F_VL_X64 = 56, + AVX512BW_X64 = 57, + AVX512BW_VL_X64 = 58, + AVX512CD_X64 = 59, + AVX512CD_VL_X64 = 60, + AVX512DQ_X64 = 61, + AVX512DQ_VL_X64 = 62, + AVX512VBMI_X64 = 63, + AVX512VBMI_VL_X64 = 64, } public enum InstructionSet_X86 @@ -290,40 +301,43 @@ public enum InstructionSet_X86 AVX512DQ_VL = 30, AVX512VBMI = 31, AVX512VBMI_VL = 32, - X86Base_X64 = 33, - SSE_X64 = 34, - SSE2_X64 = 35, - SSE3_X64 = 36, - SSSE3_X64 = 37, - SSE41_X64 = 38, - SSE42_X64 = 39, - AVX_X64 = 40, - AVX2_X64 = 41, - AES_X64 = 42, - BMI1_X64 = 43, - BMI2_X64 = 44, - FMA_X64 = 45, - LZCNT_X64 = 46, - PCLMULQDQ_X64 = 47, - POPCNT_X64 = 48, - AVXVNNI_X64 = 49, - MOVBE_X64 = 50, - X86Serialize_X64 = 51, - AVX512F_X64 = 52, - AVX512F_VL_X64 = 53, - AVX512BW_X64 = 54, - AVX512BW_VL_X64 = 55, - AVX512CD_X64 = 56, - AVX512CD_VL_X64 = 57, - AVX512DQ_X64 = 58, - AVX512DQ_VL_X64 = 59, - AVX512VBMI_X64 = 60, - AVX512VBMI_VL_X64 = 61, + VectorT128 = 33, + VectorT256 = 34, + VectorT512 = 35, + X86Base_X64 = 36, + SSE_X64 = 37, + SSE2_X64 = 38, + SSE3_X64 = 39, + SSSE3_X64 = 40, + SSE41_X64 = 41, + SSE42_X64 = 42, + AVX_X64 = 43, + AVX2_X64 = 44, + AES_X64 = 45, + BMI1_X64 = 46, + BMI2_X64 = 47, + FMA_X64 = 48, + LZCNT_X64 = 49, + PCLMULQDQ_X64 = 50, + POPCNT_X64 = 51, + AVXVNNI_X64 = 52, + MOVBE_X64 = 53, + X86Serialize_X64 = 54, + AVX512F_X64 = 55, + AVX512F_VL_X64 = 56, + AVX512BW_X64 = 57, + AVX512BW_VL_X64 = 58, + AVX512CD_X64 = 59, + AVX512CD_VL_X64 = 60, + AVX512DQ_X64 = 61, + AVX512DQ_VL_X64 = 62, + AVX512VBMI_X64 = 63, + AVX512VBMI_VL_X64 = 64, } public unsafe struct InstructionSetFlags : IEnumerable { - private const int FlagsFieldCount = 1; + private const int FlagsFieldCount = 2; private const int BitsPerFlagsField = 64; private fixed ulong _flags[FlagsFieldCount]; public IEnumerable ARM64Flags => this.Select((x) => (InstructionSet_ARM64)x); @@ -527,6 +541,8 @@ public static InstructionSetFlags ExpandInstructionSetByImplicationHelper(Target resultflags.AddInstructionSet(InstructionSet.ARM64_AdvSimd); if (resultflags.HasInstructionSet(InstructionSet.ARM64_Vector128)) resultflags.AddInstructionSet(InstructionSet.ARM64_AdvSimd); + if (resultflags.HasInstructionSet(InstructionSet.ARM64_VectorT128)) + resultflags.AddInstructionSet(InstructionSet.ARM64_AdvSimd); break; case TargetArchitecture.X64: @@ -690,24 +706,46 @@ public static InstructionSetFlags ExpandInstructionSetByImplicationHelper(Target resultflags.AddInstructionSet(InstructionSet.X64_X86Base); if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512F)) resultflags.AddInstructionSet(InstructionSet.X64_AVX2); + if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512F)) + resultflags.AddInstructionSet(InstructionSet.X64_FMA); if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512F_VL)) resultflags.AddInstructionSet(InstructionSet.X64_AVX512F); if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512CD)) resultflags.AddInstructionSet(InstructionSet.X64_AVX512F); + if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512CD_VL)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX512CD); if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512CD_VL)) resultflags.AddInstructionSet(InstructionSet.X64_AVX512F_VL); if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512BW)) resultflags.AddInstructionSet(InstructionSet.X64_AVX512F); + if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512BW_VL)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX512BW); if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512BW_VL)) resultflags.AddInstructionSet(InstructionSet.X64_AVX512F_VL); if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512DQ)) resultflags.AddInstructionSet(InstructionSet.X64_AVX512F); + if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512DQ_VL)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX512DQ); if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512DQ_VL)) resultflags.AddInstructionSet(InstructionSet.X64_AVX512F_VL); if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512VBMI)) resultflags.AddInstructionSet(InstructionSet.X64_AVX512BW); + if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512VBMI_VL)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX512VBMI); if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512VBMI_VL)) resultflags.AddInstructionSet(InstructionSet.X64_AVX512BW_VL); + if (resultflags.HasInstructionSet(InstructionSet.X64_VectorT128)) + resultflags.AddInstructionSet(InstructionSet.X64_SSE2); + if (resultflags.HasInstructionSet(InstructionSet.X64_VectorT256)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX2); + if (resultflags.HasInstructionSet(InstructionSet.X64_VectorT512)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX512F); + if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512F)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX512BW_VL); + if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512F)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX512CD_VL); + if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512F)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX512DQ_VL); break; case TargetArchitecture.X86: @@ -755,24 +793,46 @@ public static InstructionSetFlags ExpandInstructionSetByImplicationHelper(Target resultflags.AddInstructionSet(InstructionSet.X86_X86Base); if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512F)) resultflags.AddInstructionSet(InstructionSet.X86_AVX2); + if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512F)) + resultflags.AddInstructionSet(InstructionSet.X86_FMA); if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512F_VL)) resultflags.AddInstructionSet(InstructionSet.X86_AVX512F); if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512CD)) resultflags.AddInstructionSet(InstructionSet.X86_AVX512F); + if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512CD_VL)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX512CD); if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512CD_VL)) resultflags.AddInstructionSet(InstructionSet.X86_AVX512F_VL); if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512BW)) resultflags.AddInstructionSet(InstructionSet.X86_AVX512F); + if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512BW_VL)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX512BW); if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512BW_VL)) resultflags.AddInstructionSet(InstructionSet.X86_AVX512F_VL); if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512DQ)) resultflags.AddInstructionSet(InstructionSet.X86_AVX512F); + if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512DQ_VL)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX512DQ); if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512DQ_VL)) resultflags.AddInstructionSet(InstructionSet.X86_AVX512F_VL); if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512VBMI)) resultflags.AddInstructionSet(InstructionSet.X86_AVX512BW); + if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512VBMI_VL)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX512VBMI); if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512VBMI_VL)) resultflags.AddInstructionSet(InstructionSet.X86_AVX512BW_VL); + if (resultflags.HasInstructionSet(InstructionSet.X86_VectorT128)) + resultflags.AddInstructionSet(InstructionSet.X86_SSE2); + if (resultflags.HasInstructionSet(InstructionSet.X86_VectorT256)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX2); + if (resultflags.HasInstructionSet(InstructionSet.X86_VectorT512)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX512F); + if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512F)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX512BW_VL); + if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512F)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX512CD_VL); + if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512F)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX512DQ_VL); break; } } while (!oldflags.Equals(resultflags)); @@ -830,6 +890,8 @@ private static InstructionSetFlags ExpandInstructionSetByReverseImplicationHelpe resultflags.AddInstructionSet(InstructionSet.ARM64_Vector64); if (resultflags.HasInstructionSet(InstructionSet.ARM64_AdvSimd)) resultflags.AddInstructionSet(InstructionSet.ARM64_Vector128); + if (resultflags.HasInstructionSet(InstructionSet.ARM64_AdvSimd)) + resultflags.AddInstructionSet(InstructionSet.ARM64_VectorT128); break; case TargetArchitecture.X64: @@ -935,24 +997,46 @@ private static InstructionSetFlags ExpandInstructionSetByReverseImplicationHelpe resultflags.AddInstructionSet(InstructionSet.X64_X86Serialize); if (resultflags.HasInstructionSet(InstructionSet.X64_AVX2)) resultflags.AddInstructionSet(InstructionSet.X64_AVX512F); + if (resultflags.HasInstructionSet(InstructionSet.X64_FMA)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX512F); if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512F)) resultflags.AddInstructionSet(InstructionSet.X64_AVX512F_VL); if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512F)) resultflags.AddInstructionSet(InstructionSet.X64_AVX512CD); + if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512CD)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX512CD_VL); if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512F_VL)) resultflags.AddInstructionSet(InstructionSet.X64_AVX512CD_VL); if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512F)) resultflags.AddInstructionSet(InstructionSet.X64_AVX512BW); + if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512BW)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX512BW_VL); if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512F_VL)) resultflags.AddInstructionSet(InstructionSet.X64_AVX512BW_VL); if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512F)) resultflags.AddInstructionSet(InstructionSet.X64_AVX512DQ); + if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512DQ)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX512DQ_VL); if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512F_VL)) resultflags.AddInstructionSet(InstructionSet.X64_AVX512DQ_VL); if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512BW)) resultflags.AddInstructionSet(InstructionSet.X64_AVX512VBMI); + if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512VBMI)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX512VBMI_VL); if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512BW_VL)) resultflags.AddInstructionSet(InstructionSet.X64_AVX512VBMI_VL); + if (resultflags.HasInstructionSet(InstructionSet.X64_SSE2)) + resultflags.AddInstructionSet(InstructionSet.X64_VectorT128); + if (resultflags.HasInstructionSet(InstructionSet.X64_AVX2)) + resultflags.AddInstructionSet(InstructionSet.X64_VectorT256); + if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512F)) + resultflags.AddInstructionSet(InstructionSet.X64_VectorT512); + if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512BW_VL)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX512F); + if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512CD_VL)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX512F); + if (resultflags.HasInstructionSet(InstructionSet.X64_AVX512DQ_VL)) + resultflags.AddInstructionSet(InstructionSet.X64_AVX512F); break; case TargetArchitecture.X86: @@ -1000,24 +1084,46 @@ private static InstructionSetFlags ExpandInstructionSetByReverseImplicationHelpe resultflags.AddInstructionSet(InstructionSet.X86_X86Serialize); if (resultflags.HasInstructionSet(InstructionSet.X86_AVX2)) resultflags.AddInstructionSet(InstructionSet.X86_AVX512F); + if (resultflags.HasInstructionSet(InstructionSet.X86_FMA)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX512F); if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512F)) resultflags.AddInstructionSet(InstructionSet.X86_AVX512F_VL); if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512F)) resultflags.AddInstructionSet(InstructionSet.X86_AVX512CD); + if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512CD)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX512CD_VL); if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512F_VL)) resultflags.AddInstructionSet(InstructionSet.X86_AVX512CD_VL); if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512F)) resultflags.AddInstructionSet(InstructionSet.X86_AVX512BW); + if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512BW)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX512BW_VL); if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512F_VL)) resultflags.AddInstructionSet(InstructionSet.X86_AVX512BW_VL); if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512F)) resultflags.AddInstructionSet(InstructionSet.X86_AVX512DQ); + if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512DQ)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX512DQ_VL); if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512F_VL)) resultflags.AddInstructionSet(InstructionSet.X86_AVX512DQ_VL); if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512BW)) resultflags.AddInstructionSet(InstructionSet.X86_AVX512VBMI); + if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512VBMI)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX512VBMI_VL); if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512BW_VL)) resultflags.AddInstructionSet(InstructionSet.X86_AVX512VBMI_VL); + if (resultflags.HasInstructionSet(InstructionSet.X86_SSE2)) + resultflags.AddInstructionSet(InstructionSet.X86_VectorT128); + if (resultflags.HasInstructionSet(InstructionSet.X86_AVX2)) + resultflags.AddInstructionSet(InstructionSet.X86_VectorT256); + if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512F)) + resultflags.AddInstructionSet(InstructionSet.X86_VectorT512); + if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512BW_VL)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX512F); + if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512CD_VL)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX512F); + if (resultflags.HasInstructionSet(InstructionSet.X86_AVX512DQ_VL)) + resultflags.AddInstructionSet(InstructionSet.X86_AVX512F); break; } } while (!oldflags.Equals(resultflags)); @@ -1035,8 +1141,8 @@ private static InstructionSetFlags ExpandInstructionSetByReverseImplicationHelpe { ("x86-x64-v3", TargetArchitecture.X86), "x86-x64-v2 avx2 bmi bmi2 lzcnt movbe fma" }, { ("skylake", TargetArchitecture.X64), "x86-x64-v3" }, { ("skylake", TargetArchitecture.X86), "x86-x64-v3" }, - { ("x86-x64-v4", TargetArchitecture.X64), "x86-x64-v3 avx512f avx512f_vl avx512bw avx512bw_vl avx512cd avx512cd_vl" }, - { ("x86-x64-v4", TargetArchitecture.X86), "x86-x64-v3 avx512f avx512f_vl avx512bw avx512bw_vl avx512cd avx512cd_vl" }, + { ("x86-x64-v4", TargetArchitecture.X64), "x86-x64-v3 avx512f avx512f_vl avx512bw avx512bw_vl avx512cd avx512cd_vl avx512dq avx512dq_vl" }, + { ("x86-x64-v4", TargetArchitecture.X86), "x86-x64-v3 avx512f avx512f_vl avx512bw avx512bw_vl avx512cd avx512cd_vl avx512dq avx512dq_vl" }, { ("armv8-a", TargetArchitecture.ARM64), "neon" }, { ("armv8.1-a", TargetArchitecture.ARM64), "armv8-a lse crc rdma" }, { ("armv8.2-a", TargetArchitecture.ARM64), "armv8.1-a" }, @@ -1088,6 +1194,7 @@ public static IEnumerable ArchitectureToValidInstructionSets yield return new InstructionSetInfo("Vector128", "", InstructionSet.ARM64_Vector128, false); yield return new InstructionSetInfo("Dczva", "", InstructionSet.ARM64_Dczva, false); yield return new InstructionSetInfo("rcpc", "", InstructionSet.ARM64_Rcpc, true); + yield return new InstructionSetInfo("vectort128", "VectorT128", InstructionSet.ARM64_VectorT128, true); break; case TargetArchitecture.X64: @@ -1123,6 +1230,9 @@ public static IEnumerable ArchitectureToValidInstructionSets yield return new InstructionSetInfo("avx512dq_vl", "Avx512DQ_VL", InstructionSet.X64_AVX512DQ_VL, true); yield return new InstructionSetInfo("avx512vbmi", "Avx512Vbmi", InstructionSet.X64_AVX512VBMI, true); yield return new InstructionSetInfo("avx512vbmi_vl", "Avx512Vbmi_VL", InstructionSet.X64_AVX512VBMI_VL, true); + yield return new InstructionSetInfo("vectort128", "VectorT128", InstructionSet.X64_VectorT128, true); + yield return new InstructionSetInfo("vectort256", "VectorT256", InstructionSet.X64_VectorT256, true); + yield return new InstructionSetInfo("vectort512", "VectorT512", InstructionSet.X64_VectorT512, true); break; case TargetArchitecture.X86: @@ -1158,6 +1268,9 @@ public static IEnumerable ArchitectureToValidInstructionSets yield return new InstructionSetInfo("avx512dq_vl", "Avx512DQ_VL", InstructionSet.X86_AVX512DQ_VL, true); yield return new InstructionSetInfo("avx512vbmi", "Avx512Vbmi", InstructionSet.X86_AVX512VBMI, true); yield return new InstructionSetInfo("avx512vbmi_vl", "Avx512Vbmi_VL", InstructionSet.X86_AVX512VBMI_VL, true); + yield return new InstructionSetInfo("vectort128", "VectorT128", InstructionSet.X86_VectorT128, true); + yield return new InstructionSetInfo("vectort256", "VectorT256", InstructionSet.X86_VectorT256, true); + yield return new InstructionSetInfo("vectort512", "VectorT512", InstructionSet.X86_VectorT512, true); break; } } @@ -1432,6 +1545,9 @@ public static InstructionSet LookupPlatformIntrinsicInstructionSet(TargetArchite else { return InstructionSet.ARM64_Sha256; } + case "VectorT128": + { return InstructionSet.ARM64_VectorT128; } + } break; @@ -1598,6 +1714,15 @@ public static InstructionSet LookupPlatformIntrinsicInstructionSet(TargetArchite else { return InstructionSet.X64_AVX512VBMI; } + case "VectorT128": + { return InstructionSet.X64_VectorT128; } + + case "VectorT256": + { return InstructionSet.X64_VectorT256; } + + case "VectorT512": + { return InstructionSet.X64_VectorT512; } + } break; @@ -1692,6 +1817,15 @@ public static InstructionSet LookupPlatformIntrinsicInstructionSet(TargetArchite else { return InstructionSet.X86_AVX512VBMI; } + case "VectorT128": + { return InstructionSet.X86_VectorT128; } + + case "VectorT256": + { return InstructionSet.X86_VectorT256; } + + case "VectorT512": + { return InstructionSet.X86_VectorT512; } + } break; diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs index 71d8cd105dc60a..d2a792e25a0c18 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoTypes.cs @@ -1425,7 +1425,7 @@ public enum CorJitFlag : uint CORJIT_FLAG_BBINSTR_IF_LOOPS = 32, // JIT must instrument current method if it has loops CORJIT_FLAG_PUBLISH_SECRET_PARAM = 33, // JIT must place stub secret param into local 0. (used by IL stubs) CORJIT_FLAG_UNUSED9 = 34, - CORJIT_FLAG_SAMPLING_JIT_BACKGROUND = 35, // JIT is being invoked as a result of stack sampling for hot methods in the background + CORJIT_FLAG_UNUSED1 = 35, CORJIT_FLAG_USE_PINVOKE_HELPERS = 36, // The JIT should use the PINVOKE_{BEGIN,END} helpers instead of emitting inline transitions CORJIT_FLAG_REVERSE_PINVOKE = 37, // The JIT should insert REVERSE_PINVOKE_{ENTER,EXIT} helpers into method prolog/epilog CORJIT_FLAG_TRACK_TRANSITIONS = 38, // The JIT should insert the helper variants that track transitions. diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt index d5f74271ed13fb..3c669e1ea95fea 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetDesc.txt @@ -57,7 +57,9 @@ instructionset ,X86 ,Avx512DQ , ,35 ,AVX512DQ instructionset ,X86 ,Avx512DQ_VL , ,36 ,AVX512DQ_VL ,avx512dq_vl instructionset ,X86 ,Avx512Vbmi , ,37 ,AVX512VBMI ,avx512vbmi instructionset ,X86 ,Avx512Vbmi_VL , ,38 ,AVX512VBMI_VL ,avx512vbmi_vl - +instructionset ,X86 ,VectorT128 , ,39 ,VectorT128 ,vectort128 +instructionset ,X86 ,VectorT256 , ,40 ,VectorT256 ,vectort256 +instructionset ,X86 ,VectorT512 , ,41 ,VectorT512 ,vectort512 instructionset64bit,X86 ,X86Base instructionset64bit,X86 ,SSE @@ -115,15 +117,33 @@ implication ,X86 ,AVXVNNI ,AVX2 implication ,X86 ,MOVBE ,SSE42 implication ,X86 ,X86Serialize ,X86Base implication ,X86 ,AVX512F ,AVX2 +implication ,X86 ,AVX512F ,FMA implication ,X86 ,AVX512F_VL ,AVX512F implication ,X86 ,AVX512CD ,AVX512F +implication ,X86 ,AVX512CD_VL ,AVX512CD implication ,X86 ,AVX512CD_VL ,AVX512F_VL implication ,X86 ,AVX512BW ,AVX512F +implication ,X86 ,AVX512BW_VL ,AVX512BW implication ,X86 ,AVX512BW_VL ,AVX512F_VL implication ,X86 ,AVX512DQ ,AVX512F +implication ,X86 ,AVX512DQ_VL ,AVX512DQ implication ,X86 ,AVX512DQ_VL ,AVX512F_VL implication ,X86 ,AVX512VBMI ,AVX512BW +implication ,X86 ,AVX512VBMI_VL ,AVX512VBMI implication ,X86 ,AVX512VBMI_VL ,AVX512BW_VL +implication ,X86 ,VectorT128 ,SSE2 +implication ,X86 ,VectorT256 ,AVX2 +implication ,X86 ,VectorT512 ,AVX512F + +; While the AVX-512 ISAs can be individually lit-up, they really +; need F, BW, CD, DQ, and VL to be fully functional without adding +; significant complexity into the JIT. Additionally, unlike AVX/AVX2 +; there was never really any hardware that didn't provide all 5 at +; once, with the notable exception being Knight's Landing which +; provided a similar but not quite the same feature. +implication ,X86 ,AVX512F ,AVX512BW_VL +implication ,X86 ,AVX512F ,AVX512CD_VL +implication ,X86 ,AVX512F ,AVX512DQ_VL ; Definition of X64 instruction sets definearch ,X64 ,64Bit ,X64, X64 @@ -133,19 +153,20 @@ copyinstructionsets,X86 ,X64 ; Definition of Arm64 instruction sets definearch ,ARM64 ,64Bit ,Arm64, Arm64 -instructionset ,ARM64 ,ArmBase , ,16 ,ArmBase ,base -instructionset ,ARM64 ,AdvSimd , ,17 ,AdvSimd ,neon -instructionset ,ARM64 ,Aes , ,9 ,Aes ,aes -instructionset ,ARM64 ,Crc32 , ,18 ,Crc32 ,crc -instructionset ,ARM64 ,Dp , ,23 ,Dp ,dotprod -instructionset ,ARM64 ,Rdm , ,24 ,Rdm ,rdma -instructionset ,ARM64 ,Sha1 , ,19 ,Sha1 ,sha1 -instructionset ,ARM64 ,Sha256 , ,20 ,Sha256 ,sha2 -instructionset ,ARM64 , ,Atomics ,21 ,Atomics ,lse -instructionset ,ARM64 , , , ,Vector64 , -instructionset ,ARM64 , , , ,Vector128, -instructionset ,ARM64 , , , ,Dczva , -instructionset ,ARM64 , ,Rcpc ,26 ,Rcpc ,rcpc +instructionset ,ARM64 ,ArmBase , ,16 ,ArmBase ,base +instructionset ,ARM64 ,AdvSimd , ,17 ,AdvSimd ,neon +instructionset ,ARM64 ,Aes , ,9 ,Aes ,aes +instructionset ,ARM64 ,Crc32 , ,18 ,Crc32 ,crc +instructionset ,ARM64 ,Dp , ,23 ,Dp ,dotprod +instructionset ,ARM64 ,Rdm , ,24 ,Rdm ,rdma +instructionset ,ARM64 ,Sha1 , ,19 ,Sha1 ,sha1 +instructionset ,ARM64 ,Sha256 , ,20 ,Sha256 ,sha2 +instructionset ,ARM64 , ,Atomics ,21 ,Atomics ,lse +instructionset ,ARM64 , , , ,Vector64 , +instructionset ,ARM64 , , , ,Vector128 , +instructionset ,ARM64 , , , ,Dczva , +instructionset ,ARM64 , ,Rcpc ,26 ,Rcpc ,rcpc +instructionset ,ARM64 ,VectorT128 , ,39 ,VectorT128 ,vectort128 instructionset64bit,ARM64 ,ArmBase instructionset64bit,ARM64 ,AdvSimd @@ -159,16 +180,16 @@ instructionset64bit,ARM64 ,Sha256 vectorinstructionset,ARM64,Vector64 vectorinstructionset,ARM64,Vector128 -implication ,ARM64 ,AdvSimd ,ArmBase -implication ,ARM64 ,Aes ,ArmBase -implication ,ARM64 ,Crc32 ,ArmBase -implication ,ARM64 ,Dp ,AdvSimd -implication ,ARM64 ,Rdm ,AdvSimd -implication ,ARM64 ,Sha1 ,ArmBase -implication ,ARM64 ,Sha256 ,ArmBase -implication ,ARM64 ,Vector64 ,AdvSimd -implication ,ARM64 ,Vector128 ,AdvSimd - +implication ,ARM64 ,AdvSimd ,ArmBase +implication ,ARM64 ,Aes ,ArmBase +implication ,ARM64 ,Crc32 ,ArmBase +implication ,ARM64 ,Dp ,AdvSimd +implication ,ARM64 ,Rdm ,AdvSimd +implication ,ARM64 ,Sha1 ,ArmBase +implication ,ARM64 ,Sha256 ,ArmBase +implication ,ARM64 ,Vector64 ,AdvSimd +implication ,ARM64 ,Vector128 ,AdvSimd +implication ,ARM64 ,VectorT128 ,AdvSimd ; ,name and aliases ,archs ,lower baselines included by implication ; @@ -176,7 +197,7 @@ instructionsetgroup ,x86-x64 ,X64 X86 ,sse2 instructionsetgroup ,x86-x64-v2 ,X64 X86 ,sse4.2 popcnt instructionsetgroup ,x86-x64-v3 ,X64 X86 ,x86-x64-v2 avx2 bmi bmi2 lzcnt movbe fma instructionsetgroup ,skylake ,X64 X86 ,x86-x64-v3 -instructionsetgroup ,x86-x64-v4 ,X64 X86 ,x86-x64-v3 avx512f avx512f_vl avx512bw avx512bw_vl avx512cd avx512cd_vl +instructionsetgroup ,x86-x64-v4 ,X64 X86 ,x86-x64-v3 avx512f avx512f_vl avx512bw avx512bw_vl avx512cd avx512cd_vl avx512dq avx512dq_vl instructionsetgroup ,armv8-a ,ARM64 ,neon instructionsetgroup ,armv8.1-a ,ARM64 ,armv8-a lse crc rdma diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs index 4547b91e2fdc70..3ce3bf5a795dbd 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/InstructionSetGenerator.cs @@ -95,7 +95,7 @@ public InstructionSetImplication(string architecture, InstructionSetImplication private Dictionary _64BitVariantArchitectureManagedNameSuffix = new Dictionary(); // This represents the number of flags fields we currently track - private const int FlagsFieldCount = 1; + private const int FlagsFieldCount = 2; private void ArchitectureEncountered(string arch) { diff --git a/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs b/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs index 99305804f53519..fb4cd6bf17157f 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs @@ -73,6 +73,11 @@ private static class FieldLayoutFlags /// True if the type transitively has an Int128 in it or is an Int128 /// public const int IsInt128OrHasInt128Fields = 0x800; + + /// + /// True if the type transitively has a Vector in it or is Vector + /// + public const int IsVectorTOrHasVectorTFields = 0x1000; } private sealed class StaticBlockInfo @@ -153,6 +158,21 @@ public virtual bool IsInt128OrHasInt128Fields } } + /// + /// Is a type Vector or transitively have any fields of a type Vector. + /// + public virtual bool IsVectorTOrHasVectorTFields + { + get + { + if (!_fieldLayoutFlags.HasFlags(FieldLayoutFlags.ComputedInstanceTypeLayout)) + { + ComputeInstanceLayout(InstanceLayoutKind.TypeAndFields); + } + return _fieldLayoutFlags.HasFlags(FieldLayoutFlags.IsVectorTOrHasVectorTFields); + } + } + /// /// The number of bytes required to hold a field of this type /// @@ -451,6 +471,10 @@ public void ComputeInstanceLayout(InstanceLayoutKind layoutKind) { _fieldLayoutFlags.AddFlags(FieldLayoutFlags.IsInt128OrHasInt128Fields); } + if (computedLayout.IsVectorTOrHasVectorTFields) + { + _fieldLayoutFlags.AddFlags(FieldLayoutFlags.IsVectorTOrHasVectorTFields); + } if (computedLayout.Offsets != null) { diff --git a/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs index 53388c915b85d8..31a46ec47f6416 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs @@ -84,6 +84,7 @@ public struct ComputedInstanceFieldLayout public bool LayoutAbiStable; // Is the layout stable such that it can safely be used in function calling conventions public bool IsAutoLayoutOrHasAutoLayoutFields; public bool IsInt128OrHasInt128Fields; + public bool IsVectorTOrHasVectorTFields; /// /// If Offsets is non-null, then all field based layout is complete. diff --git a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs index 0fc9064fb00a81..d56bfa19bbf210 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs @@ -110,6 +110,7 @@ out instanceByteSizeAndAlignment LayoutAbiStable = true, IsAutoLayoutOrHasAutoLayoutFields = false, IsInt128OrHasInt128Fields = false, + IsVectorTOrHasVectorTFields = false, }; if (numInstanceFields > 0) @@ -211,7 +212,7 @@ public override ComputedStaticFieldLayout ComputeStaticFieldLayout(DefType defTy } ref StaticsBlock block = ref GetStaticsBlockForField(ref result, field); - SizeAndAlignment sizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout: false, context.Target.DefaultPackingSize, out bool _, out bool _, out bool _); + SizeAndAlignment sizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout: false, context.Target.DefaultPackingSize, out bool _, out bool _, out bool _, out bool _); block.Size = LayoutInt.AlignUp(block.Size, sizeAndAlignment.Alignment, context.Target); result.Offsets[index] = new FieldAndOffset(field, block.Size); @@ -303,18 +304,27 @@ protected ComputedInstanceFieldLayout ComputeExplicitFieldLayout(MetadataType ty int fieldOrdinal = 0; bool layoutAbiStable = true; bool hasAutoLayoutField = false; - bool hasInt128Field = type.BaseType == null ? false : type.BaseType.IsInt128OrHasInt128Fields; + bool hasInt128Field = false; + bool hasVectorTField = false; + + if (type.BaseType is not null) + { + hasInt128Field = type.BaseType.IsInt128OrHasInt128Fields; + hasVectorTField = type.BaseType.IsVectorTOrHasVectorTFields; + } foreach (var fieldAndOffset in layoutMetadata.Offsets) { TypeDesc fieldType = fieldAndOffset.Field.FieldType; - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout, out bool fieldHasInt128Field); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout, out bool fieldHasInt128Field, out bool fieldHasVectorTField); if (!fieldLayoutAbiStable) layoutAbiStable = false; if (fieldHasAutoLayout) hasAutoLayoutField = true; if (fieldHasInt128Field) hasInt128Field = true; + if (fieldHasVectorTField) + hasVectorTField = true; largestAlignmentRequired = LayoutInt.Max(fieldSizeAndAlignment.Alignment, largestAlignmentRequired); @@ -367,6 +377,7 @@ protected ComputedInstanceFieldLayout ComputeExplicitFieldLayout(MetadataType ty { IsAutoLayoutOrHasAutoLayoutFields = hasAutoLayoutField, IsInt128OrHasInt128Fields = hasInt128Field, + IsVectorTOrHasVectorTFields = hasVectorTField, }; computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; computedLayout.FieldSize = instanceSizeAndAlignment.Size; @@ -402,20 +413,29 @@ protected ComputedInstanceFieldLayout ComputeSequentialFieldLayout(MetadataType int packingSize = ComputePackingSize(type, layoutMetadata); bool layoutAbiStable = true; bool hasAutoLayoutField = false; - bool hasInt128Field = type.BaseType == null ? false : type.BaseType.IsInt128OrHasInt128Fields; + bool hasInt128Field = false; + bool hasVectorTField = false; + + if (type.BaseType is not null) + { + hasInt128Field = type.BaseType.IsInt128OrHasInt128Fields; + hasVectorTField = type.BaseType.IsVectorTOrHasVectorTFields; + } foreach (var field in type.GetFields()) { if (field.IsStatic) continue; - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout, out bool fieldHasInt128Field); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType.UnderlyingType, hasLayout: true, packingSize, out bool fieldLayoutAbiStable, out bool fieldHasAutoLayout, out bool fieldHasInt128Field, out bool fieldHasVectorTField); if (!fieldLayoutAbiStable) layoutAbiStable = false; if (fieldHasAutoLayout) hasAutoLayoutField = true; if (fieldHasInt128Field) hasInt128Field = true; + if (fieldHasVectorTField) + hasVectorTField = true; largestAlignmentRequirement = LayoutInt.Max(fieldSizeAndAlignment.Alignment, largestAlignmentRequirement); @@ -443,6 +463,7 @@ protected ComputedInstanceFieldLayout ComputeSequentialFieldLayout(MetadataType { IsAutoLayoutOrHasAutoLayoutFields = hasAutoLayoutField, IsInt128OrHasInt128Fields = hasInt128Field, + IsVectorTOrHasVectorTFields = hasVectorTField, }; computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; computedLayout.FieldSize = instanceSizeAndAlignment.Size; @@ -517,6 +538,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, int instanceGCPointerFieldsCount = 0; int[] instanceNonGCPointerFieldsCount = new int[maxLog2Size + 1]; bool hasInt128Field = false; + bool hasVectorTField = false; foreach (var field in type.GetFields()) { @@ -531,6 +553,8 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, instanceValueClassFieldCount++; if (((DefType)fieldType).IsInt128OrHasInt128Fields) hasInt128Field = true; + if (((DefType)fieldType).IsVectorTOrHasVectorTFields) + hasVectorTField = true; } else if (fieldType.IsGCPointer) { @@ -540,7 +564,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, { Debug.Assert(fieldType.IsPrimitive || fieldType.IsPointer || fieldType.IsFunctionPointer || fieldType.IsEnum || fieldType.IsByRef); - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool _, out bool _, out bool _); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool _, out bool _, out bool _, out bool _); instanceNonGCPointerFieldsCount[CalculateLog2(fieldSizeAndAlignment.Size.AsInt)]++; } } @@ -577,7 +601,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, TypeDesc fieldType = field.FieldType; - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _, out bool _); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _, out bool _, out bool _); if (!fieldLayoutAbiStable) layoutAbiStable = false; @@ -747,7 +771,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, for (int i = 0; i < instanceValueClassFieldsArr.Length; i++) { // Align the cumulative field offset to the indeterminate value - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(instanceValueClassFieldsArr[i].FieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _, out bool _); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(instanceValueClassFieldsArr[i].FieldType, hasLayout, packingSize, out bool fieldLayoutAbiStable, out bool _, out bool _, out bool _); if (!fieldLayoutAbiStable) layoutAbiStable = false; @@ -804,6 +828,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, { IsAutoLayoutOrHasAutoLayoutFields = true, IsInt128OrHasInt128Fields = hasInt128Field, + IsVectorTOrHasVectorTFields = hasVectorTField, }; computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; computedLayout.FieldSize = instanceSizeAndAlignment.Size; @@ -817,7 +842,7 @@ protected ComputedInstanceFieldLayout ComputeAutoFieldLayout(MetadataType type, private static void PlaceInstanceField(FieldDesc field, bool hasLayout, int packingSize, FieldAndOffset[] offsets, ref LayoutInt instanceFieldPos, ref int fieldOrdinal, LayoutInt offsetBias) { - var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType, hasLayout, packingSize, out bool _, out bool _, out bool _); + var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType, hasLayout, packingSize, out bool _, out bool _, out bool _, out bool _); instanceFieldPos = AlignUpInstanceFieldOffset(instanceFieldPos, fieldSizeAndAlignment.Alignment, field.Context.Target); offsets[fieldOrdinal] = new FieldAndOffset(field, instanceFieldPos + offsetBias); @@ -877,12 +902,13 @@ public LayoutInt CalculateFieldBaseOffset(MetadataType type, bool requiresAlign8 return cumulativeInstanceFieldPos; } - private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, bool hasLayout, int packingSize, out bool layoutAbiStable, out bool fieldTypeHasAutoLayout, out bool fieldTypeHasInt128Field) + private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, bool hasLayout, int packingSize, out bool layoutAbiStable, out bool fieldTypeHasAutoLayout, out bool fieldTypeHasInt128Field, out bool fieldTypeHasVectorTField) { SizeAndAlignment result; layoutAbiStable = true; fieldTypeHasAutoLayout = true; fieldTypeHasInt128Field = false; + fieldTypeHasVectorTField = false; if (fieldType.IsDefType) { @@ -894,6 +920,7 @@ private static SizeAndAlignment ComputeFieldSizeAndAlignment(TypeDesc fieldType, layoutAbiStable = defType.LayoutAbiStable; fieldTypeHasAutoLayout = defType.IsAutoLayoutOrHasAutoLayoutFields; fieldTypeHasInt128Field = defType.IsInt128OrHasInt128Fields; + fieldTypeHasVectorTField = defType.IsVectorTOrHasVectorTFields; } else { diff --git a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs index cb80143d94250d..3aa6ca2db11a16 100644 --- a/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs +++ b/src/coreclr/tools/Common/TypeSystem/Interop/IL/MarshalHelpers.cs @@ -422,6 +422,12 @@ internal static MarshallerKind GetMarshallerKind( return MarshallerKind.Invalid; } + if (!isField && ((DefType)type).IsVectorTOrHasVectorTFields) + { + // Vector types or structs that contain them cannot be passed by value + return MarshallerKind.Invalid; + } + if (MarshalUtils.IsBlittableType(type)) { if (nativeType != NativeTypeKind.Default && nativeType != NativeTypeKind.Struct) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.csproj index 3ddbde70bd2f08..4512bbfd88e7d0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Compiler.Tests/ILCompiler.Compiler.Tests.csproj @@ -17,7 +17,6 @@ - diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerGeneratedInteropStubManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerGeneratedInteropStubManager.cs index b56ca367618e9a..16cb8dcc6e8bb8 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerGeneratedInteropStubManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/CompilerGeneratedInteropStubManager.cs @@ -32,10 +32,10 @@ public sealed override PInvokeILProvider CreatePInvokeILProvider() public sealed override void AddToReadyToRunHeader(ReadyToRunHeaderNode header, NodeFactory nodeFactory, ExternalReferencesTableNode commonFixupsTableNode) { var delegateMapNode = new DelegateMarshallingStubMapNode(commonFixupsTableNode, _interopStateManager); - header.Add(MetadataManager.BlobIdToReadyToRunSection(ReflectionMapBlob.DelegateMarshallingStubMap), delegateMapNode, delegateMapNode, delegateMapNode.EndSymbol); + header.Add(MetadataManager.BlobIdToReadyToRunSection(ReflectionMapBlob.DelegateMarshallingStubMap), delegateMapNode); var structMapNode = new StructMarshallingStubMapNode(commonFixupsTableNode, _interopStateManager); - header.Add(MetadataManager.BlobIdToReadyToRunSection(ReflectionMapBlob.StructMarshallingStubMap), structMapNode, structMapNode, structMapNode.EndSymbol); + header.Add(MetadataManager.BlobIdToReadyToRunSection(ReflectionMapBlob.StructMarshallingStubMap), structMapNode); } } } 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 d32757d162d80b..c2132ce7aa6d1f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs @@ -239,30 +239,24 @@ private void ReportWarningsForReflectionAccess(in MessageOrigin origin, TypeSyst // This is because reflection access is actually problematic on all members which are in a "requires" scope // so for example even instance methods. See for example https://github.com/dotnet/linker/issues/3140 - it's possible // to call a method on a "null" instance via reflection. - if (_logger.ShouldSuppressAnalysisWarningsForRequires(entity, DiagnosticUtilities.RequiresUnreferencedCodeAttribute, out CustomAttributeValue? requiresAttribute)) - { - if (!ShouldSkipWarningsForOverride(entity, accessKind)) + if (_logger.ShouldSuppressAnalysisWarningsForRequires(entity, DiagnosticUtilities.RequiresUnreferencedCodeAttribute, out CustomAttributeValue? requiresAttribute) && + ShouldProduceRequiresWarningForReflectionAccess(entity, accessKind)) ReportRequires(origin, entity, DiagnosticUtilities.RequiresUnreferencedCodeAttribute, requiresAttribute.Value); - } - if (_logger.ShouldSuppressAnalysisWarningsForRequires(entity, DiagnosticUtilities.RequiresAssemblyFilesAttribute, out requiresAttribute)) - { - if (!ShouldSkipWarningsForOverride(entity, accessKind)) + if (_logger.ShouldSuppressAnalysisWarningsForRequires(entity, DiagnosticUtilities.RequiresAssemblyFilesAttribute, out requiresAttribute) && + ShouldProduceRequiresWarningForReflectionAccess(entity, accessKind)) ReportRequires(origin, entity, DiagnosticUtilities.RequiresAssemblyFilesAttribute, requiresAttribute.Value); - } - if (_logger.ShouldSuppressAnalysisWarningsForRequires(entity, DiagnosticUtilities.RequiresDynamicCodeAttribute, out requiresAttribute)) - { - if (!ShouldSkipWarningsForOverride(entity, accessKind)) + if (_logger.ShouldSuppressAnalysisWarningsForRequires(entity, DiagnosticUtilities.RequiresDynamicCodeAttribute, out requiresAttribute) && + ShouldProduceRequiresWarningForReflectionAccess(entity, accessKind)) ReportRequires(origin, entity, DiagnosticUtilities.RequiresDynamicCodeAttribute, requiresAttribute.Value); - } // Below is about accessing DAM annotated members, so only RUC is applicable as a suppression scope if (_logger.ShouldSuppressAnalysisWarningsForRequires(origin.MemberDefinition, DiagnosticUtilities.RequiresUnreferencedCodeAttribute)) return; bool isReflectionAccessCoveredByDAM = Annotations.ShouldWarnWhenAccessedForReflection(entity); - if (isReflectionAccessCoveredByDAM && !ShouldSkipWarningsForOverride(entity, accessKind)) + if (isReflectionAccessCoveredByDAM && ShouldProduceRequiresWarningForReflectionAccess(entity, accessKind)) { if (entity is MethodDesc) _logger.LogWarning(origin, DiagnosticId.DynamicallyAccessedMembersMethodAccessedViaReflection, entity.GetDisplayName()); @@ -273,16 +267,16 @@ private void ReportWarningsForReflectionAccess(in MessageOrigin origin, TypeSyst // We decided to not warn on reflection access to compiler-generated methods: // https://github.com/dotnet/runtime/issues/85042 - // All override methods should have the same annotations as their base methods - // (else we will produce warning IL2046 or IL2092 or some other warning). - // When marking override methods via DynamicallyAccessedMembers, we should only issue a warning for the base method. - // PERF: Avoid precomputing this as this method is relatively expensive. Only call it once we're about to produce a warning. - static bool ShouldSkipWarningsForOverride(TypeSystemEntity entity, AccessKind accessKind) + static bool ShouldProduceRequiresWarningForReflectionAccess(TypeSystemEntity entity, AccessKind accessKind) { - if (accessKind != AccessKind.DynamicallyAccessedMembersMark || entity is not MethodDesc method || !method.IsVirtual) - return false; + bool isCompilerGenerated = CompilerGeneratedState.IsNestedFunctionOrStateMachineMember(entity); - return MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(method) != method; + // Compiler generated code accessed via a token is considered a "hard" reference + // even though we also have to treat it as reflection access. + // So we need to enforce RUC check/warn in this case. + bool forceRequiresWarning = accessKind == AccessKind.TokenAccess; + + return !isCompilerGenerated || forceRequiresWarning; } } @@ -319,7 +313,8 @@ static bool IsDeclaredWithinType(TypeSystemEntity member, TypeDesc type) // causing problems is pretty low. bool isReflectionAccessCoveredByRUC = _logger.ShouldSuppressAnalysisWarningsForRequires(entity, DiagnosticUtilities.RequiresUnreferencedCodeAttribute, out CustomAttributeValue? requiresUnreferencedCodeAttribute); - if (isReflectionAccessCoveredByRUC && !ShouldSkipWarningsForOverride(entity)) + bool isCompilerGenerated = CompilerGeneratedState.IsNestedFunctionOrStateMachineMember(entity); + if (isReflectionAccessCoveredByRUC && !isCompilerGenerated) { var id = reportOnMember ? DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberWithRequiresUnreferencedCode : DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberOnBaseWithRequiresUnreferencedCode; _logger.LogWarning(origin, id, _typeHierarchyDataFlowOrigin.GetDisplayName(), @@ -329,7 +324,7 @@ static bool IsDeclaredWithinType(TypeSystemEntity member, TypeDesc type) } bool isReflectionAccessCoveredByDAM = Annotations.ShouldWarnWhenAccessedForReflection(entity); - if (isReflectionAccessCoveredByDAM && !ShouldSkipWarningsForOverride(entity)) + if (isReflectionAccessCoveredByDAM && !isCompilerGenerated) { var id = reportOnMember ? DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberWithDynamicallyAccessedMembers : DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberOnBaseWithDynamicallyAccessedMembers; _logger.LogWarning(origin, id, _typeHierarchyDataFlowOrigin.GetDisplayName(), entity.GetDisplayName()); @@ -337,17 +332,6 @@ static bool IsDeclaredWithinType(TypeSystemEntity member, TypeDesc type) // We decided to not warn on reflection access to compiler-generated methods: // https://github.com/dotnet/runtime/issues/85042 - - // All override methods should have the same annotations as their base methods - // (else we will produce warning IL2046 or IL2092 or some other warning). - // When marking override methods via DynamicallyAccessedMembers, we should only issue a warning for the base method. - static bool ShouldSkipWarningsForOverride(TypeSystemEntity entity) - { - if (entity is not MethodDesc method || !method.IsVirtual) - return false; - - return MetadataVirtualMethodAlgorithm.FindSlotDefiningMethodForVirtualMethod(method) != method; - } } private void ReportRequires(in MessageOrigin origin, TypeSystemEntity entity, string requiresAttributeName, in CustomAttributeValue requiresAttribute) 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 6bf674b28296a4..f8207e8454f9c5 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayMapNode.cs @@ -12,18 +12,17 @@ namespace ILCompiler.DependencyAnalysis /// /// Represents a hash table of array types generated into the image. /// - internal sealed class ArrayMapNode : ObjectNode, ISymbolDefinitionNode + internal sealed class ArrayMapNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private ObjectAndOffsetSymbolNode _endSymbol; - private ExternalReferencesTableNode _externalReferences; + private readonly ExternalReferencesTableNode _externalReferences; + private int? _size; public ArrayMapNode(ExternalReferencesTableNode externalReferences) { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__array_type_map_End", true); _externalReferences = externalReferences; } - public ISymbolDefinitionNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { @@ -68,9 +67,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) byte[] hashTableBytes = writer.Save(); - _endSymbol.SetSymbolOffset(hashTableBytes.Length); + _size = hashTableBytes.Length; - return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } protected internal override int Phase => (int)ObjectNodePhase.Ordered; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayOfEmbeddedDataNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayOfEmbeddedDataNode.cs index 2e75de7ead91e9..f63dab431e7190 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayOfEmbeddedDataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayOfEmbeddedDataNode.cs @@ -5,24 +5,22 @@ namespace ILCompiler.DependencyAnalysis { - public interface IHasStartSymbol - { - ObjectAndOffsetSymbolNode StartSymbol { get; } - } - /// /// Represents an array of nodes. The contents of this node will be emitted /// by placing a starting symbol, followed by contents of nodes (optionally /// sorted using provided comparer), followed by ending symbol. /// - public class ArrayOfEmbeddedDataNode : EmbeddedDataContainerNode, IHasStartSymbol + public class ArrayOfEmbeddedDataNode : EmbeddedDataContainerNode, INodeWithSize where TEmbedded : EmbeddedObjectNode { + private int? _size; private HashSet _nestedNodes = new HashSet(); private List _nestedNodesList = new List(); private IComparer _sorter; - public ArrayOfEmbeddedDataNode(string startSymbolMangledName, string endSymbolMangledName, IComparer nodeSorter) : base(startSymbolMangledName, endSymbolMangledName) + int INodeWithSize.Size => _size.Value; + + public ArrayOfEmbeddedDataNode(string mangledName, IComparer nodeSorter) : base(mangledName) { _sorter = nodeSorter; } @@ -35,11 +33,10 @@ public void AddEmbeddedObject(TEmbedded symbol) { _nestedNodesList.Add(symbol); } - symbol.ContainingNode = this; } } - protected override string GetName(NodeFactory factory) => $"Region {StartSymbol.GetMangledName(factory.NameMangler)}"; + protected override string GetName(NodeFactory factory) => $"Region {this.GetMangledName(factory.NameMangler)}"; public override ObjectNodeSection GetSection(NodeFactory factory) => ObjectNodeSection.DataSection; public override bool IsShareable => false; @@ -84,12 +81,11 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly) if (_sorter != null) _nestedNodesList.Sort(_sorter); - builder.AddSymbol(StartSymbol); + builder.AddSymbol(this); GetElementDataForNodes(ref builder, factory, relocsOnly); - EndSymbol.SetSymbolOffset(builder.CountBytes); - builder.AddSymbol(EndSymbol); + _size = builder.CountBytes; ObjectData objData = builder.ToObjectData(); return objData; @@ -100,15 +96,6 @@ public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) return _nestedNodesList.Count == 0; } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) - { - DependencyList dependencies = new DependencyList(); - dependencies.Add(StartSymbol, "StartSymbol"); - dependencies.Add(EndSymbol, "EndSymbol"); - - return dependencies; - } - protected internal override int Phase => (int)ObjectNodePhase.Ordered; public override int ClassCode => (int)ObjectNodeOrder.ArrayOfEmbeddedDataNode; 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 ba9e73eccfbfee..a2bc613dcbd4f6 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs @@ -24,13 +24,12 @@ public sealed class ArrayOfEmbeddedPointersNode : ArrayOfEmbeddedDataNo /// public delegate void OnMarkedDelegate(EmbeddedPointerIndirectionNode embeddedObject); - public ArrayOfEmbeddedPointersNode(string startSymbolMangledName, string endSymbolMangledName, IComparer nodeSorter) + public ArrayOfEmbeddedPointersNode(string mangledName, IComparer nodeSorter) : base( - startSymbolMangledName, - endSymbolMangledName, + mangledName, nodeSorter != null ? new PointerIndirectionNodeComparer(nodeSorter) : null) { - _startSymbolMangledName = startSymbolMangledName; + _startSymbolMangledName = mangledName; } public EmbeddedObjectNode NewNode(TTarget target) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayOfFrozenObjectsNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayOfFrozenObjectsNode.cs index a83b93447fa67e..e6ca20b6507d27 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayOfFrozenObjectsNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ArrayOfFrozenObjectsNode.cs @@ -8,15 +8,10 @@ namespace ILCompiler.DependencyAnalysis { - public class ArrayOfFrozenObjectsNode : DehydratableObjectNode, ISymbolDefinitionNode + public class ArrayOfFrozenObjectsNode : DehydratableObjectNode, ISymbolDefinitionNode, INodeWithSize { - private readonly ObjectAndOffsetSymbolNode _endSymbol; - public ISymbolNode EndSymbol => _endSymbol; - - public ArrayOfFrozenObjectsNode() - { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__FrozenSegmentEnd", true); - } + private int? _size; + int INodeWithSize.Size => _size.Value; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) => sb.Append(nameMangler.CompilationUnitPrefix).Append("__FrozenSegmentStart"); @@ -61,8 +56,7 @@ protected override ObjectData GetDehydratableData(NodeFactory factory, bool relo AlignNextObject(ref builder, factory); builder.EmitZeroPointer(); - _endSymbol.SetSymbolOffset(builder.CountBytes); - builder.AddSymbol(_endSymbol); + _size = builder.CountBytes; return builder.ToObjectData(); } 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 8adf1643302b73..b1a97f9d5bf7f1 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ByRefTypeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ByRefTypeMapNode.cs @@ -11,18 +11,17 @@ namespace ILCompiler.DependencyAnalysis /// /// Represents a hash table of ByRef types generated into the image. /// - internal sealed class ByRefTypeMapNode : ObjectNode, ISymbolDefinitionNode + internal sealed class ByRefTypeMapNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private readonly ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; private readonly ExternalReferencesTableNode _externalReferences; public ByRefTypeMapNode(ExternalReferencesTableNode externalReferences) { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__byref_type_map_End", true); _externalReferences = externalReferences; } - public ISymbolDefinitionNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { @@ -62,9 +61,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) byte[] hashTableBytes = writer.Save(); - _endSymbol.SetSymbolOffset(hashTableBytes.Length); + _size = hashTableBytes.Length; - return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } protected internal override int Phase => (int)ObjectNodePhase.Ordered; 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 2f84a816e0fffb..ec0e162367693f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ClassConstructorContextMap.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ClassConstructorContextMap.cs @@ -11,18 +11,17 @@ namespace ILCompiler.DependencyAnalysis { - internal sealed class ClassConstructorContextMap : ObjectNode, ISymbolDefinitionNode + internal sealed class ClassConstructorContextMap : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; private ExternalReferencesTableNode _externalReferences; public ClassConstructorContextMap(ExternalReferencesTableNode externalReferences) { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__type_to_cctorContext_map_End", true); _externalReferences = externalReferences; } - public ISymbolDefinitionNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { @@ -74,9 +73,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) byte[] hashTableBytes = writer.Save(); - _endSymbol.SetSymbolOffset(hashTableBytes.Length); + _size = hashTableBytes.Length; - return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } protected internal override int Phase => (int)ObjectNodePhase.Ordered; 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 fcaf3c4ea9a3be..4e526961690e17 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DehydratedDataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DehydratedDataNode.cs @@ -28,14 +28,9 @@ namespace ILCompiler.DependencyAnalysis /// * Generate N bytes of zeros. /// * Generate a relocation to Nth entry in the lookup table that supplements the dehydrated stream. /// - internal sealed class DehydratedDataNode : ObjectNode, ISymbolDefinitionNode + internal sealed class DehydratedDataNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private ObjectAndOffsetSymbolNode _endSymbol; - - public DehydratedDataNode() - { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__dehydrated_data_End", true); - } + private int? _size; public override bool IsShareable => false; @@ -47,7 +42,7 @@ public DehydratedDataNode() public int Offset => 0; - public ISymbolNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { @@ -87,7 +82,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) if (firstSymbol != null) builder.EmitReloc(firstSymbol, RelocType.IMAGE_REL_BASED_RELPTR32, -firstSymbol.Offset); else - return new ObjectData(Array.Empty(), Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(Array.Empty(), Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); // Sort the reloc targets and create reloc lookup table. KeyValuePair[] relocSort = new List>(relocOccurences).ToArray(); @@ -312,8 +307,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) dehydratedSegmentPosition += o.Data.Length; } - _endSymbol.SetSymbolOffset(builder.CountBytes); - builder.AddSymbol(_endSymbol); + _size = builder.CountBytes; // Dehydrated data is followed by the reloc lookup table. for (int i = 0; i < relocSort.Length; i++) 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 1176f0e1bf4a5a..2111f081a697d9 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DelegateMarshallingStubMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DelegateMarshallingStubMapNode.cs @@ -12,20 +12,19 @@ namespace ILCompiler.DependencyAnalysis /// /// Represents a hash table of delegate marshalling stub types generated into the image. /// - internal sealed class DelegateMarshallingStubMapNode : ObjectNode, ISymbolDefinitionNode + internal sealed class DelegateMarshallingStubMapNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private readonly ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; private readonly ExternalReferencesTableNode _externalReferences; private readonly InteropStateManager _interopStateManager; public DelegateMarshallingStubMapNode(ExternalReferencesTableNode externalReferences, InteropStateManager interopStateManager) { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__delegate_marshalling_stub_map_End", true); _externalReferences = externalReferences; _interopStateManager = interopStateManager; } - public ISymbolDefinitionNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { @@ -71,9 +70,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) byte[] hashTableBytes = writer.Save(); - _endSymbol.SetSymbolOffset(hashTableBytes.Length); + _size = hashTableBytes.Length; - return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } protected internal override int Phase => (int)ObjectNodePhase.Ordered; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedObjectNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedObjectNode.cs index 511f91cbb56f22..33b7594383c49a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedObjectNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EmbeddedObjectNode.cs @@ -16,8 +16,6 @@ public abstract class EmbeddedObjectNode : SortableDependencyNode private int _offset; private int _index; - public IHasStartSymbol ContainingNode { get; set; } - public EmbeddedObjectNode() { _offset = InvalidOffset; 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 3d52e0a3a9c22a..46d38a7b9857b1 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExactMethodInstantiationsNode.cs @@ -13,14 +13,13 @@ namespace ILCompiler.DependencyAnalysis /// /// Hashtable of all exact (non-canonical) generic method instantiations compiled in the module. /// - public sealed class ExactMethodInstantiationsNode : ObjectNode, ISymbolDefinitionNode + public sealed class ExactMethodInstantiationsNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; private ExternalReferencesTableNode _externalReferences; public ExactMethodInstantiationsNode(ExternalReferencesTableNode externalReferences) { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__exact_method_instantiations_End", true); _externalReferences = externalReferences; } @@ -29,7 +28,7 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) sb.Append(nameMangler.CompilationUnitPrefix).Append("__exact_method_instantiations"); } - public ISymbolDefinitionNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public int Offset => 0; public override bool IsShareable => false; public override ObjectNodeSection GetSection(NodeFactory factory) => _externalReferences.GetSection(factory); @@ -99,9 +98,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) byte[] streamBytes = nativeWriter.Save(); - _endSymbol.SetSymbolOffset(streamBytes.Length); + _size = streamBytes.Length; - return new ObjectData(streamBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(streamBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } public static void GetExactMethodInstantiationDependenciesForMethod(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternalReferencesTableNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternalReferencesTableNode.cs index 3c2c3d29289724..86e2d14a0f3c29 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternalReferencesTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ExternalReferencesTableNode.cs @@ -13,9 +13,9 @@ namespace ILCompiler.DependencyAnalysis /// /// Represents a node that points to various symbols and can be sequentially addressed. /// - public sealed class ExternalReferencesTableNode : ObjectNode, ISymbolDefinitionNode + public sealed class ExternalReferencesTableNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private readonly ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; private readonly string _blobName; private readonly NodeFactory _nodeFactory; @@ -25,11 +25,10 @@ public sealed class ExternalReferencesTableNode : ObjectNode, ISymbolDefinitionN public ExternalReferencesTableNode(string blobName, NodeFactory nodeFactory) { _blobName = blobName; - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__external_" + blobName + "_references_End", true); _nodeFactory = nodeFactory; } - public ISymbolDefinitionNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { @@ -103,10 +102,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) } } - _endSymbol.SetSymbolOffset(builder.CountBytes); + _size = builder.CountBytes; builder.AddSymbol(this); - builder.AddSymbol(_endSymbol); return builder.ToObjectData(); } 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 f2651f9069f1bf..979b8d4ef618a7 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FunctionPointerMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FunctionPointerMapNode.cs @@ -12,18 +12,17 @@ namespace ILCompiler.DependencyAnalysis /// /// Represents a hash table of function pointer types generated into the image. /// - internal sealed class FunctionPointerMapNode : ObjectNode, ISymbolDefinitionNode + internal sealed class FunctionPointerMapNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private readonly ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; private readonly ExternalReferencesTableNode _externalReferences; public FunctionPointerMapNode(ExternalReferencesTableNode externalReferences) { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__fnptr_type_map_End", true); _externalReferences = externalReferences; } - public ISymbolDefinitionNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { @@ -71,9 +70,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) byte[] hashTableBytes = writer.Save(); - _endSymbol.SetSymbolOffset(hashTableBytes.Length); + _size = hashTableBytes.Length; - return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } protected internal override int Phase => (int)ObjectNodePhase.Ordered; 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 9e69b3d98d6770..aeae01fa7cd2c6 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsHashtableNode.cs @@ -13,14 +13,13 @@ namespace ILCompiler.DependencyAnalysis /// /// Represents a hashtable of all compiled generic method instantiations /// - public sealed class GenericMethodsHashtableNode : ObjectNode, ISymbolDefinitionNode + public sealed class GenericMethodsHashtableNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; private ExternalReferencesTableNode _externalReferences; public GenericMethodsHashtableNode(ExternalReferencesTableNode externalReferences) { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__generic_methods_hashtable_End", true); _externalReferences = externalReferences; } @@ -29,7 +28,7 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) sb.Append(nameMangler.CompilationUnitPrefix).Append("__generic_methods_hashtable"); } - public ISymbolNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public int Offset => 0; public override bool IsShareable => false; public override ObjectNodeSection GetSection(NodeFactory factory) => _externalReferences.GetSection(factory); @@ -92,9 +91,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) byte[] streamBytes = nativeWriter.Save(); - _endSymbol.SetSymbolOffset(streamBytes.Length); + _size = streamBytes.Length; - return new ObjectData(streamBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(streamBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } public static void GetGenericMethodsHashtableDependenciesForMethod(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) 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 971c81d1ef89db..6230518cf2b258 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericMethodsTemplateMap.cs @@ -13,14 +13,13 @@ namespace ILCompiler.DependencyAnalysis /// /// Hashtable of all generic method templates used by the TypeLoader at runtime /// - public sealed class GenericMethodsTemplateMap : ObjectNode, ISymbolDefinitionNode + public sealed class GenericMethodsTemplateMap : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; private ExternalReferencesTableNode _externalReferences; public GenericMethodsTemplateMap(ExternalReferencesTableNode externalReferences) { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__GenericMethodsTemplateMap_End", true); _externalReferences = externalReferences; } @@ -29,7 +28,7 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) sb.Append(nameMangler.CompilationUnitPrefix).Append("__GenericMethodsTemplateMap"); } - public ISymbolNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public int Offset => 0; public override bool IsShareable => false; public override ObjectNodeSection GetSection(NodeFactory factory) => _externalReferences.GetSection(factory); @@ -73,9 +72,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) byte[] streamBytes = nativeWriter.Save(); - _endSymbol.SetSymbolOffset(streamBytes.Length); + _size = streamBytes.Length; - return new ObjectData(streamBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(streamBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } public static void GetTemplateMethodDependencies(ref DependencyList dependencies, NodeFactory factory, MethodDesc method) 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 c1f06e34ef5a3d..fa1a70b3544acc 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericTypesHashtableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericTypesHashtableNode.cs @@ -12,14 +12,13 @@ namespace ILCompiler.DependencyAnalysis /// /// Represents a hashtable of all compiled generic type instantiations /// - public sealed class GenericTypesHashtableNode : ObjectNode, ISymbolDefinitionNode + public sealed class GenericTypesHashtableNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; private ExternalReferencesTableNode _externalReferences; public GenericTypesHashtableNode(ExternalReferencesTableNode externalReferences) { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__generic_types_hashtable_End", true); _externalReferences = externalReferences; } @@ -28,7 +27,7 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) sb.Append(nameMangler.CompilationUnitPrefix).Append("__generic_types_hashtable"); } - public ISymbolNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public int Offset => 0; public override bool IsShareable => false; public override ObjectNodeSection GetSection(NodeFactory factory) => _externalReferences.GetSection(factory); @@ -68,9 +67,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) byte[] streamBytes = nativeWriter.Save(); - _endSymbol.SetSymbolOffset(streamBytes.Length); + _size = streamBytes.Length; - return new ObjectData(streamBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(streamBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } protected internal override int Phase => (int)ObjectNodePhase.Ordered; 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 9a329b0a74140d..80f44e60948d45 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericTypesTemplateMap.cs @@ -13,14 +13,13 @@ namespace ILCompiler.DependencyAnalysis /// /// Hashtable of all generic type templates used by the TypeLoader at runtime /// - public sealed class GenericTypesTemplateMap : ObjectNode, ISymbolDefinitionNode + public sealed class GenericTypesTemplateMap : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; private ExternalReferencesTableNode _externalReferences; public GenericTypesTemplateMap(ExternalReferencesTableNode externalReferences) { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__GenericTypesTemplateMap_End", true); _externalReferences = externalReferences; } @@ -29,7 +28,7 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) sb.Append(nameMangler.CompilationUnitPrefix).Append("__GenericTypesTemplateMap"); } - public ISymbolNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public int Offset => 0; public override bool IsShareable => false; public override ObjectNodeSection GetSection(NodeFactory factory) => _externalReferences.GetSection(factory); @@ -68,9 +67,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) byte[] streamBytes = nativeWriter.Save(); - _endSymbol.SetSymbolOffset(streamBytes.Length); + _size = streamBytes.Length; - return new ObjectData(streamBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(streamBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } public static void GetTemplateTypeDependencies(ref DependencyList dependencies, NodeFactory factory, TypeDesc type) 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 c1847c5d06f5f4..7769b2b6a60872 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericVirtualMethodTableNode.cs @@ -14,15 +14,14 @@ namespace ILCompiler.DependencyAnalysis /// /// Represents a map of generic virtual method implementations. /// - public sealed class GenericVirtualMethodTableNode : ObjectNode, ISymbolDefinitionNode + public sealed class GenericVirtualMethodTableNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; private ExternalReferencesTableNode _externalReferences; private Dictionary> _gvmImplementations; public GenericVirtualMethodTableNode(ExternalReferencesTableNode externalReferences) { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__gvm_table_End", true); _externalReferences = externalReferences; _gvmImplementations = new Dictionary>(); } @@ -32,7 +31,7 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) sb.Append(nameMangler.CompilationUnitPrefix).Append("__gvm_table"); } - public ISymbolNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public int Offset => 0; public override bool IsShareable => false; public override ObjectNodeSection GetSection(NodeFactory factory) => _externalReferences.GetSection(factory); @@ -135,9 +134,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) byte[] streamBytes = nativeFormatWriter.Save(); - _endSymbol.SetSymbolOffset(streamBytes.Length); + _size = streamBytes.Length; - return new ObjectData(streamBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(streamBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } protected internal override int Phase => (int)ObjectNodePhase.Ordered; 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 b5855ce04e43d2..74de063bbd706d 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceGenericVirtualMethodTableNode.cs @@ -15,16 +15,15 @@ namespace ILCompiler.DependencyAnalysis /// /// Represents a map between reflection metadata and generated method bodies. /// - public sealed class InterfaceGenericVirtualMethodTableNode : ObjectNode, ISymbolDefinitionNode + public sealed class InterfaceGenericVirtualMethodTableNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; private ExternalReferencesTableNode _externalReferences; private Dictionary> _interfaceGvmSlots; private Dictionary>> _interfaceImpls; public InterfaceGenericVirtualMethodTableNode(ExternalReferencesTableNode externalReferences) { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__interface_gvm_table_End", true); _externalReferences = externalReferences; _interfaceGvmSlots = new Dictionary>(); _interfaceImpls = new Dictionary>>(); @@ -34,7 +33,7 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(nameMangler.CompilationUnitPrefix).Append("__interface_gvm_table"); } - public ISymbolNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public int Offset => 0; public override bool IsShareable => false; public override ObjectNodeSection GetSection(NodeFactory factory) => _externalReferences.GetSection(factory); @@ -225,9 +224,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) byte[] streamBytes = nativeFormatWriter.Save(); - _endSymbol.SetSymbolOffset(streamBytes.Length); + _size = streamBytes.Length; - return new ObjectData(streamBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(streamBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } protected internal override int Phase => (int)ObjectNodePhase.Ordered; 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 d17ecfb8126d8b..ad84d1bd81ed6a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MetadataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/MetadataNode.cs @@ -11,16 +11,11 @@ namespace ILCompiler.DependencyAnalysis /// Represents a blob of native metadata describing assemblies, the types in them, and their members. /// The data is used at runtime to e.g. support reflection. /// - public sealed class MetadataNode : ObjectNode, ISymbolDefinitionNode + public sealed class MetadataNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; - public MetadataNode() - { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__embedded_metadata_End", true); - } - - public ISymbolNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { @@ -42,7 +37,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) return new ObjectData(Array.Empty(), Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); byte[] blob = factory.MetadataManager.GetMetadataBlob(factory); - _endSymbol.SetSymbolOffset(blob.Length); + _size = blob.Length; return new ObjectData( blob, @@ -50,8 +45,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) 1, new ISymbolDefinitionNode[] { - this, - _endSymbol + this }); } 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 fe53861e70ca44..185274addeb0d9 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleInitializerListNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ModuleInitializerListNode.cs @@ -10,16 +10,11 @@ namespace ILCompiler.DependencyAnalysis { - internal sealed class ModuleInitializerListNode : ObjectNode, ISymbolDefinitionNode + internal sealed class ModuleInitializerListNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private readonly ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; - public ModuleInitializerListNode() - { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__module_initializers_End", true); - } - - public ISymbolNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { @@ -137,7 +132,6 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.RequireInitialAlignment(factory.Target.PointerSize); builder.AddSymbol(this); - builder.AddSymbol(_endSymbol); foreach (var module in sortedModules) { @@ -150,7 +144,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) var result = builder.ToObjectData(); - _endSymbol.SetSymbolOffset(result.Data.Length); + _size = result.Data.Length; return result; } 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 e9bc60848daf05..95e73168567505 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutInfoNode.cs @@ -12,9 +12,9 @@ namespace ILCompiler.DependencyAnalysis /// /// Native layout info blob. /// - public sealed class NativeLayoutInfoNode : ObjectNode, ISymbolDefinitionNode + public sealed class NativeLayoutInfoNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; private ExternalReferencesTableNode _externalReferences; private ExternalReferencesTableNode _staticsReferences; @@ -29,7 +29,6 @@ public sealed class NativeLayoutInfoNode : ObjectNode, ISymbolDefinitionNode public NativeLayoutInfoNode(ExternalReferencesTableNode externalReferences, ExternalReferencesTableNode staticsReferences) { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__nativelayoutinfo_End", true); _externalReferences = externalReferences; _staticsReferences = staticsReferences; @@ -45,7 +44,7 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(nameMangler.CompilationUnitPrefix).Append("__nativelayoutinfo"); } - public ISymbolNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public int Offset => 0; public override bool IsShareable => false; public override ObjectNodeSection GetSection(NodeFactory factory) => _externalReferences.GetSection(factory); @@ -87,9 +86,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) SaveNativeLayoutInfoWriter(factory); - _endSymbol.SetSymbolOffset(_writerSavedBytes.Length); + _size = _writerSavedBytes.Length; - return new ObjectData(_writerSavedBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(_writerSavedBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } protected internal override int Phase => (int)ObjectNodePhase.Ordered; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs index 53b44d32b142c7..5d734957ff6e75 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NodeFactory.cs @@ -1250,18 +1250,15 @@ public string GetSymbolAlternateName(ISymbolNode node) } public ArrayOfEmbeddedPointersNode GCStaticsRegion = new ArrayOfEmbeddedPointersNode( - "__GCStaticRegionStart", - "__GCStaticRegionEnd", + "__GCStaticRegion", new SortableDependencyNode.ObjectNodeComparer(CompilerComparer.Instance)); public ArrayOfEmbeddedDataNode ThreadStaticsRegion = new ArrayOfEmbeddedDataNode( - "__ThreadStaticRegionStart", - "__ThreadStaticRegionEnd", + "__ThreadStaticRegion", new SortableDependencyNode.EmbeddedObjectNodeComparer(CompilerComparer.Instance)); public ArrayOfEmbeddedPointersNode EagerCctorTable = new ArrayOfEmbeddedPointersNode( - "__EagerCctorStart", - "__EagerCctorEnd", + "__EagerCctor", null); public ArrayOfFrozenObjectsNode FrozenSegmentRegion = new ArrayOfFrozenObjectsNode(); @@ -1296,18 +1293,18 @@ public virtual void AttachToDependencyGraph(DependencyAnalyzerBase graph.AddRoot(_inlinedThreadStatiscNode, "Inlined threadstatics are used if present"); } - ReadyToRunHeader.Add(ReadyToRunSectionType.GCStaticRegion, GCStaticsRegion, GCStaticsRegion.StartSymbol, GCStaticsRegion.EndSymbol); - ReadyToRunHeader.Add(ReadyToRunSectionType.ThreadStaticRegion, ThreadStaticsRegion, ThreadStaticsRegion.StartSymbol, ThreadStaticsRegion.EndSymbol); - ReadyToRunHeader.Add(ReadyToRunSectionType.EagerCctor, EagerCctorTable, EagerCctorTable.StartSymbol, EagerCctorTable.EndSymbol); - ReadyToRunHeader.Add(ReadyToRunSectionType.TypeManagerIndirection, TypeManagerIndirection, TypeManagerIndirection); - ReadyToRunHeader.Add(ReadyToRunSectionType.FrozenObjectRegion, FrozenSegmentRegion, FrozenSegmentRegion, FrozenSegmentRegion.EndSymbol); - ReadyToRunHeader.Add(ReadyToRunSectionType.ModuleInitializerList, ModuleInitializerList, ModuleInitializerList, ModuleInitializerList.EndSymbol); + ReadyToRunHeader.Add(ReadyToRunSectionType.GCStaticRegion, GCStaticsRegion); + ReadyToRunHeader.Add(ReadyToRunSectionType.ThreadStaticRegion, ThreadStaticsRegion); + ReadyToRunHeader.Add(ReadyToRunSectionType.EagerCctor, EagerCctorTable); + ReadyToRunHeader.Add(ReadyToRunSectionType.TypeManagerIndirection, TypeManagerIndirection); + ReadyToRunHeader.Add(ReadyToRunSectionType.FrozenObjectRegion, FrozenSegmentRegion); + ReadyToRunHeader.Add(ReadyToRunSectionType.ModuleInitializerList, ModuleInitializerList); var commonFixupsTableNode = new ExternalReferencesTableNode("CommonFixupsTable", this); InteropStubManager.AddToReadyToRunHeader(ReadyToRunHeader, this, commonFixupsTableNode); MetadataManager.AddToReadyToRunHeader(ReadyToRunHeader, this, commonFixupsTableNode); MetadataManager.AttachToDependencyGraph(graph); - ReadyToRunHeader.Add(MetadataManager.BlobIdToReadyToRunSection(ReflectionMapBlob.CommonFixupsTable), commonFixupsTableNode, commonFixupsTableNode, commonFixupsTableNode.EndSymbol); + ReadyToRunHeader.Add(MetadataManager.BlobIdToReadyToRunSection(ReflectionMapBlob.CommonFixupsTable), commonFixupsTableNode); } protected struct MethodKey : IEquatable 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 497c1f58092cb0..bf2ecfb4c71616 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PointerTypeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/PointerTypeMapNode.cs @@ -11,18 +11,17 @@ namespace ILCompiler.DependencyAnalysis /// /// Represents a hash table of pointer types generated into the image. /// - internal sealed class PointerTypeMapNode : ObjectNode, ISymbolDefinitionNode + internal sealed class PointerTypeMapNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private readonly ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; private readonly ExternalReferencesTableNode _externalReferences; public PointerTypeMapNode(ExternalReferencesTableNode externalReferences) { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__ptr_type_map_End", true); _externalReferences = externalReferences; } - public ISymbolDefinitionNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { @@ -62,9 +61,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) byte[] hashTableBytes = writer.Save(); - _endSymbol.SetSymbolOffset(hashTableBytes.Length); + _size = hashTableBytes.Length; - return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } protected internal override int Phase => (int)ObjectNodePhase.Ordered; 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 199b5a1e342dd6..e92c6804bbef2b 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunHeaderNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReadyToRunHeaderNode.cs @@ -5,7 +5,8 @@ using Internal.Runtime; using Internal.Text; -using Internal.TypeSystem; + +using Debug = System.Diagnostics.Debug; namespace ILCompiler.DependencyAnalysis { @@ -13,25 +14,21 @@ public class ReadyToRunHeaderNode : ObjectNode, ISymbolDefinitionNode { private struct HeaderItem { - public HeaderItem(ReadyToRunSectionType id, ObjectNode node, ISymbolNode startSymbol, ISymbolNode endSymbol) + public HeaderItem(ReadyToRunSectionType id, ObjectNode node) { Id = id; Node = node; - StartSymbol = startSymbol; - EndSymbol = endSymbol; } public readonly ReadyToRunSectionType Id; public readonly ObjectNode Node; - public readonly ISymbolNode StartSymbol; - public readonly ISymbolNode EndSymbol; } private List _items = new List(); - public void Add(ReadyToRunSectionType id, ObjectNode node, ISymbolNode startSymbol, ISymbolNode endSymbol = null) + public void Add(ReadyToRunSectionType id, T node) where T : ObjectNode, ISymbolDefinitionNode { - _items.Add(new HeaderItem(id, node, startSymbol, endSymbol)); + _items.Add(new HeaderItem(id, node)); } public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) @@ -93,17 +90,17 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) builder.EmitInt((int)item.Id); ModuleInfoFlags flags = 0; - if (item.EndSymbol != null) + if (item.Node is INodeWithSize) { flags |= ModuleInfoFlags.HasEndPointer; } builder.EmitInt((int)flags); - builder.EmitPointerReloc(item.StartSymbol); + builder.EmitPointerReloc((ISymbolNode)item.Node); - if (item.EndSymbol != null) + if (!relocsOnly && item.Node is INodeWithSize nodeWithSize) { - builder.EmitPointerReloc(item.EndSymbol); + builder.EmitPointerReloc((ISymbolNode)item.Node, nodeWithSize.Size); } else { @@ -117,6 +114,12 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) return builder.ToObjectData(); } - public override int ClassCode => -534800244; + protected internal override int Phase => (int)ObjectNodePhase.Late; + public override int ClassCode => 0x7db08464; + } + + public interface INodeWithSize + { + public int Size { get; } } } 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 3044fd4d979d07..8ea831f1efdb8f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionFieldMapNode.cs @@ -14,18 +14,17 @@ namespace ILCompiler.DependencyAnalysis /// /// Represents a map between reflection metadata and native field offsets. /// - internal sealed class ReflectionFieldMapNode : ObjectNode, ISymbolDefinitionNode + internal sealed class ReflectionFieldMapNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; private ExternalReferencesTableNode _externalReferences; public ReflectionFieldMapNode(ExternalReferencesTableNode externalReferences) { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__field_to_offset_map_End", true); _externalReferences = externalReferences; } - public ISymbolNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { @@ -183,9 +182,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) byte[] hashTableBytes = writer.Save(); - _endSymbol.SetSymbolOffset(hashTableBytes.Length); + _size = hashTableBytes.Length; - return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } protected internal override int Phase => (int)ObjectNodePhase.Ordered; 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 171a3f83ac227e..b46f2303c20f03 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionInvokeMapNode.cs @@ -15,24 +15,17 @@ namespace ILCompiler.DependencyAnalysis /// /// Represents a map between reflection metadata and generated method bodies. /// - internal sealed class ReflectionInvokeMapNode : ObjectNode, ISymbolDefinitionNode + internal sealed class ReflectionInvokeMapNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; private ExternalReferencesTableNode _externalReferences; public ReflectionInvokeMapNode(ExternalReferencesTableNode externalReferences) { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__method_to_entrypoint_map_End", true); _externalReferences = externalReferences; } - public ISymbolNode EndSymbol - { - get - { - return _endSymbol; - } - } + int INodeWithSize.Size => _size.Value; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { @@ -240,9 +233,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) byte[] hashTableBytes = writer.Save(); - _endSymbol.SetSymbolOffset(hashTableBytes.Length); + _size = hashTableBytes.Length; - return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } protected internal override int Phase => (int)ObjectNodePhase.Ordered; 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 e28f18387bf954..9e62841554db2f 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ReflectionVirtualInvokeMapNode.cs @@ -17,14 +17,13 @@ namespace ILCompiler.DependencyAnalysis /// Represents a map containing the necessary information needed to resolve /// a virtual method target called through reflection. /// - internal sealed class ReflectionVirtualInvokeMapNode : ObjectNode, ISymbolDefinitionNode + internal sealed class ReflectionVirtualInvokeMapNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; private ExternalReferencesTableNode _externalReferences; public ReflectionVirtualInvokeMapNode(ExternalReferencesTableNode externalReferences) { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__VirtualInvokeMap_End", true); _externalReferences = externalReferences; } @@ -33,7 +32,7 @@ public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) sb.Append(nameMangler.CompilationUnitPrefix).Append("__VirtualInvokeMap"); } - public ISymbolNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public int Offset => 0; public override bool IsShareable => false; public override ObjectNodeSection GetSection(NodeFactory factory) => _externalReferences.GetSection(factory); @@ -207,9 +206,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) byte[] hashTableBytes = writer.Save(); - _endSymbol.SetSymbolOffset(hashTableBytes.Length); + _size = hashTableBytes.Length; - return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } protected internal override int Phase => (int)ObjectNodePhase.Ordered; 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 903d4c21ffb9e1..6248fbd8c806c9 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ResourceDataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ResourceDataNode.cs @@ -18,21 +18,17 @@ namespace ILCompiler.DependencyAnalysis /// Resources are simply copied from the inputs and concatenated into this blob. /// All format information is provided by /// - internal sealed class ResourceDataNode : ObjectNode, ISymbolDefinitionNode + internal sealed class ResourceDataNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { + private int? _size; + /// /// Resource index information generated while extracting resources into the data blob /// private List _indexData; private int _totalLength; - public ResourceDataNode() - { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__embedded_resourcedata_End", true); - } - - private ObjectAndOffsetSymbolNode _endSymbol; - public ISymbolDefinitionNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public override bool IsShareable => false; @@ -62,8 +58,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) 1, new ISymbolDefinitionNode[] { - this, - EndSymbol + this }); } @@ -141,7 +136,7 @@ private byte[] GenerateResourceBlob(NodeFactory factory) currentPos += resourceData.Length; } - _endSymbol.SetSymbolOffset(resourceBlob.Length); + _size = resourceBlob.Length; return resourceBlob; } 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 21504fd1e0e48e..6d312258a7ded0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ResourceIndexNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ResourceIndexNode.cs @@ -11,19 +11,18 @@ namespace ILCompiler.DependencyAnalysis /// /// Represents a hash table of resources within the resource blob in the image. /// - internal sealed class ResourceIndexNode : ObjectNode, ISymbolDefinitionNode + internal sealed class ResourceIndexNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { private ResourceDataNode _resourceDataNode; public ResourceIndexNode(ResourceDataNode resourceDataNode) { _resourceDataNode = resourceDataNode; - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__embedded_resourceindex_End", true); } - private ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; - public ISymbolDefinitionNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public override bool IsShareable => false; @@ -53,8 +52,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) 1, new ISymbolDefinitionNode[] { - this, - EndSymbol + this }); } @@ -90,7 +88,7 @@ private byte[] GenerateIndexBlob(NodeFactory factory) } byte[] blob = nativeWriter.Save(); - _endSymbol.SetSymbolOffset(blob.Length); + _size = blob.Length; return blob; } 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 9a277122333f42..2a7fb40f17c359 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StackTraceMethodMappingNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StackTraceMethodMappingNode.cs @@ -10,15 +10,11 @@ namespace ILCompiler.DependencyAnalysis /// /// BlobIdStackTraceMethodRvaToTokenMapping - list of 8-byte pairs (method RVA-method token) /// - public sealed class StackTraceMethodMappingNode : ObjectNode, ISymbolDefinitionNode + public sealed class StackTraceMethodMappingNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - public StackTraceMethodMappingNode() - { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "_stacktrace_methodRVA_to_token_mapping_End", true); - } + private int? _size; - private ObjectAndOffsetSymbolNode _endSymbol; - public ISymbolDefinitionNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public override bool IsShareable => false; @@ -50,7 +46,6 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly); objData.RequireInitialPointerAlignment(); objData.AddSymbol(this); - objData.AddSymbol(_endSymbol); foreach (var mappingEntry in factory.MetadataManager.GetStackTraceMapping(factory)) { @@ -58,7 +53,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) objData.EmitInt(mappingEntry.MetadataHandle); } - _endSymbol.SetSymbolOffset(objData.CountBytes); + _size = objData.CountBytes; return objData.ToObjectData(); } } 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 bfa05c4dd69b0b..4a1d8d94f3e90e 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StaticsInfoHashtableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StaticsInfoHashtableNode.cs @@ -13,20 +13,19 @@ namespace ILCompiler.DependencyAnalysis /// /// Represents a hashtable with information about all statics regions for all compiled generic types. /// - internal sealed class StaticsInfoHashtableNode : ObjectNode, ISymbolDefinitionNode + internal sealed class StaticsInfoHashtableNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; private ExternalReferencesTableNode _externalReferences; private ExternalReferencesTableNode _nativeStaticsReferences; public StaticsInfoHashtableNode(ExternalReferencesTableNode externalReferences, ExternalReferencesTableNode nativeStaticsReferences) { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "_StaticsInfoHashtableNode_End", true); _externalReferences = externalReferences; _nativeStaticsReferences = nativeStaticsReferences; } - public ISymbolNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { @@ -108,9 +107,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) byte[] hashTableBytes = writer.Save(); - _endSymbol.SetSymbolOffset(hashTableBytes.Length); + _size = hashTableBytes.Length; - return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } protected internal override int Phase => (int)ObjectNodePhase.Ordered; 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 c2f5ddf791b9e8..ed0c278aa11504 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StructMarshallingStubMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/StructMarshallingStubMapNode.cs @@ -14,20 +14,19 @@ namespace ILCompiler.DependencyAnalysis /// /// Represents a hash table of struct marshalling stub types generated into the image. /// - internal sealed class StructMarshallingStubMapNode : ObjectNode, ISymbolDefinitionNode + internal sealed class StructMarshallingStubMapNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private readonly ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; private readonly ExternalReferencesTableNode _externalReferences; private readonly InteropStateManager _interopStateManager; public StructMarshallingStubMapNode(ExternalReferencesTableNode externalReferences, InteropStateManager interopStateManager) { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__struct_marshalling_stub_map_End", true); _externalReferences = externalReferences; _interopStateManager = interopStateManager; } - public ISymbolDefinitionNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { @@ -115,9 +114,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) byte[] hashTableBytes = writer.Save(); - _endSymbol.SetSymbolOffset(hashTableBytes.Length); + _size = hashTableBytes.Length; - return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } protected internal override int Phase => (int)ObjectNodePhase.Ordered; 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 2c638a08bbdfe2..a23f5e4540dfaf 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeMetadataMapNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/TypeMetadataMapNode.cs @@ -11,18 +11,17 @@ namespace ILCompiler.DependencyAnalysis /// /// Represents a map between EETypes and metadata records within the . /// - public sealed class TypeMetadataMapNode : ObjectNode, ISymbolDefinitionNode + public sealed class TypeMetadataMapNode : ObjectNode, ISymbolDefinitionNode, INodeWithSize { - private ObjectAndOffsetSymbolNode _endSymbol; + private int? _size; private ExternalReferencesTableNode _externalReferences; public TypeMetadataMapNode(ExternalReferencesTableNode externalReferences) { - _endSymbol = new ObjectAndOffsetSymbolNode(this, 0, "__type_to_metadata_map_End", true); _externalReferences = externalReferences; } - public ISymbolNode EndSymbol => _endSymbol; + int INodeWithSize.Size => _size.Value; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { @@ -70,9 +69,9 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) byte[] hashTableBytes = writer.Save(); - _endSymbol.SetSymbolOffset(hashTableBytes.Length); + _size = hashTableBytes.Length; - return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this, _endSymbol }); + return new ObjectData(hashTableBytes, Array.Empty(), 1, new ISymbolDefinitionNode[] { this }); } protected internal override int Phase => (int)ObjectNodePhase.Ordered; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSwitchManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSwitchManager.cs index 7d406ce0be2963..a1dfaeca37930c 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSwitchManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/FeatureSwitchManager.cs @@ -28,7 +28,13 @@ public class FeatureSwitchManager : ILProvider public FeatureSwitchManager(ILProvider nestedILProvider, Logger logger, IEnumerable> switchValues) { _nestedILProvider = nestedILProvider; - _hashtable = new FeatureSwitchHashtable(logger, new Dictionary(switchValues)); + + // Last setting wins + var dictionary = new Dictionary(); + foreach ((string name, bool value) in switchValues) + dictionary[name] = value; + + _hashtable = new FeatureSwitchHashtable(logger, dictionary); } private BodySubstitution GetSubstitution(MethodDesc method) diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/HardwareIntrinsicHelpers.Aot.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/HardwareIntrinsicHelpers.Aot.cs index 1411ca7b6c7941..cd7a616c0698b3 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/HardwareIntrinsicHelpers.Aot.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/HardwareIntrinsicHelpers.Aot.cs @@ -111,6 +111,10 @@ private static class XArchIntrinsicConstants public const int Avx512dq_vl = 0x400000; public const int Avx512Vbmi = 0x800000; public const int Avx512Vbmi_vl = 0x1000000; + public const int Serialize = 0x2000000; + public const int VectorT128 = 0x4000000; + public const int VectorT256 = 0x8000000; + public const int VectorT512 = 0x10000000; public static int FromInstructionSet(InstructionSet instructionSet) { @@ -120,6 +124,7 @@ public static int FromInstructionSet(InstructionSet instructionSet) return instructionSet switch { + // Optional ISAs - only available via opt-in or opportunistic light-up InstructionSet.X64_AES => Aes, InstructionSet.X64_AES_X64 => Aes, InstructionSet.X64_PCLMULQDQ => Pclmulqdq, @@ -170,8 +175,10 @@ public static int FromInstructionSet(InstructionSet instructionSet) InstructionSet.X64_AVX512VBMI_X64 => Avx512Vbmi, InstructionSet.X64_AVX512VBMI_VL => Avx512Vbmi_vl, InstructionSet.X64_AVX512VBMI_VL_X64 => Avx512Vbmi_vl, + InstructionSet.X64_X86Serialize => Serialize, + InstructionSet.X64_X86Serialize_X64 => Serialize, - // SSE and SSE2 are baseline ISAs - they're always available + // Baseline ISAs - they're always available InstructionSet.X64_SSE => 0, InstructionSet.X64_SSE_X64 => 0, InstructionSet.X64_SSE2 => 0, @@ -180,6 +187,11 @@ public static int FromInstructionSet(InstructionSet instructionSet) InstructionSet.X64_X86Base => 0, InstructionSet.X64_X86Base_X64 => 0, + // Vector Sizes + InstructionSet.X64_VectorT128 => VectorT128, + InstructionSet.X64_VectorT256 => VectorT256, + InstructionSet.X64_VectorT512 => VectorT512, + _ => throw new NotSupportedException(((InstructionSet_X64)instructionSet).ToString()) }; } @@ -196,13 +208,20 @@ private static class Arm64IntrinsicConstants public const int Sha256 = 0x0040; public const int Atomics = 0x0080; public const int Rcpc = 0x0100; + public const int VectorT128 = 0x0200; public static int FromInstructionSet(InstructionSet instructionSet) { return instructionSet switch { + + // Baseline ISAs - they're always available + InstructionSet.ARM64_ArmBase => 0, + InstructionSet.ARM64_ArmBase_Arm64 => 0, InstructionSet.ARM64_AdvSimd => AdvSimd, InstructionSet.ARM64_AdvSimd_Arm64 => AdvSimd, + + // Optional ISAs - only available via opt-in or opportunistic light-up InstructionSet.ARM64_Aes => Aes, InstructionSet.ARM64_Aes_Arm64 => Aes, InstructionSet.ARM64_Crc32 => Crc32, @@ -218,8 +237,8 @@ public static int FromInstructionSet(InstructionSet instructionSet) InstructionSet.ARM64_Atomics => Atomics, InstructionSet.ARM64_Rcpc => Rcpc, - InstructionSet.ARM64_ArmBase => 0, - InstructionSet.ARM64_ArmBase_Arm64 => 0, + // Vector Sizes + InstructionSet.ARM64_VectorT128 => VectorT128, _ => throw new NotSupportedException(((InstructionSet_ARM64)instructionSet).ToString()) }; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs index 10d7ae4edf0335..26dc3ff32e73cc 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/MetadataManager.cs @@ -122,83 +122,83 @@ internal static ReadyToRunSectionType BlobIdToReadyToRunSection(ReflectionMapBlo public virtual void AddToReadyToRunHeader(ReadyToRunHeaderNode header, NodeFactory nodeFactory, ExternalReferencesTableNode commonFixupsTableNode) { var metadataNode = new MetadataNode(); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.EmbeddedMetadata), metadataNode, metadataNode, metadataNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.EmbeddedMetadata), metadataNode); var nativeReferencesTableNode = new ExternalReferencesTableNode("NativeReferences", nodeFactory); var nativeStaticsTableNode = new ExternalReferencesTableNode("NativeStatics", nodeFactory); var resourceDataNode = new ResourceDataNode(); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.BlobIdResourceData), resourceDataNode, resourceDataNode, resourceDataNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.BlobIdResourceData), resourceDataNode); var resourceIndexNode = new ResourceIndexNode(resourceDataNode); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.BlobIdResourceIndex), resourceIndexNode, resourceIndexNode, resourceIndexNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.BlobIdResourceIndex), resourceIndexNode); var typeMapNode = new TypeMetadataMapNode(commonFixupsTableNode); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.TypeMap), typeMapNode, typeMapNode, typeMapNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.TypeMap), typeMapNode); var cctorContextMapNode = new ClassConstructorContextMap(commonFixupsTableNode); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.CCtorContextMap), cctorContextMapNode, cctorContextMapNode, cctorContextMapNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.CCtorContextMap), cctorContextMapNode); var invokeMapNode = new ReflectionInvokeMapNode(commonFixupsTableNode); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.InvokeMap), invokeMapNode, invokeMapNode, invokeMapNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.InvokeMap), invokeMapNode); var arrayMapNode = new ArrayMapNode(commonFixupsTableNode); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.ArrayMap), arrayMapNode, arrayMapNode, arrayMapNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.ArrayMap), arrayMapNode); var byRefMapNode = new ByRefTypeMapNode(commonFixupsTableNode); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.ByRefTypeMap), byRefMapNode, byRefMapNode, byRefMapNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.ByRefTypeMap), byRefMapNode); var pointerMapNode = new PointerTypeMapNode(commonFixupsTableNode); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.PointerTypeMap), pointerMapNode, pointerMapNode, pointerMapNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.PointerTypeMap), pointerMapNode); var functionPointerMapNode = new FunctionPointerMapNode(commonFixupsTableNode); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.FunctionPointerTypeMap), functionPointerMapNode, functionPointerMapNode, functionPointerMapNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.FunctionPointerTypeMap), functionPointerMapNode); var fieldMapNode = new ReflectionFieldMapNode(commonFixupsTableNode); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.FieldAccessMap), fieldMapNode, fieldMapNode, fieldMapNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.FieldAccessMap), fieldMapNode); NativeLayoutInfo = new NativeLayoutInfoNode(nativeReferencesTableNode, nativeStaticsTableNode); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.NativeLayoutInfo), NativeLayoutInfo, NativeLayoutInfo, NativeLayoutInfo.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.NativeLayoutInfo), NativeLayoutInfo); var exactMethodInstantiations = new ExactMethodInstantiationsNode(nativeReferencesTableNode); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.ExactMethodInstantiationsHashtable), exactMethodInstantiations, exactMethodInstantiations, exactMethodInstantiations.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.ExactMethodInstantiationsHashtable), exactMethodInstantiations); var genericsTypesHashtableNode = new GenericTypesHashtableNode(nativeReferencesTableNode); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.GenericsHashtable), genericsTypesHashtableNode, genericsTypesHashtableNode, genericsTypesHashtableNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.GenericsHashtable), genericsTypesHashtableNode); var genericMethodsHashtableNode = new GenericMethodsHashtableNode(nativeReferencesTableNode); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.GenericMethodsHashtable), genericMethodsHashtableNode, genericMethodsHashtableNode, genericMethodsHashtableNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.GenericMethodsHashtable), genericMethodsHashtableNode); var genericVirtualMethodTableNode = new GenericVirtualMethodTableNode(commonFixupsTableNode); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.GenericVirtualMethodTable), genericVirtualMethodTableNode, genericVirtualMethodTableNode, genericVirtualMethodTableNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.GenericVirtualMethodTable), genericVirtualMethodTableNode); var interfaceGenericVirtualMethodTableNode = new InterfaceGenericVirtualMethodTableNode(commonFixupsTableNode); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.InterfaceGenericVirtualMethodTable), interfaceGenericVirtualMethodTableNode, interfaceGenericVirtualMethodTableNode, interfaceGenericVirtualMethodTableNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.InterfaceGenericVirtualMethodTable), interfaceGenericVirtualMethodTableNode); var genericMethodsTemplatesMapNode = new GenericMethodsTemplateMap(commonFixupsTableNode); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.GenericMethodsTemplateMap), genericMethodsTemplatesMapNode, genericMethodsTemplatesMapNode, genericMethodsTemplatesMapNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.GenericMethodsTemplateMap), genericMethodsTemplatesMapNode); var genericTypesTemplatesMapNode = new GenericTypesTemplateMap(commonFixupsTableNode); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.TypeTemplateMap), genericTypesTemplatesMapNode, genericTypesTemplatesMapNode, genericTypesTemplatesMapNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.TypeTemplateMap), genericTypesTemplatesMapNode); var staticsInfoHashtableNode = new StaticsInfoHashtableNode(nativeReferencesTableNode, nativeStaticsTableNode); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.StaticsInfoHashtable), staticsInfoHashtableNode, staticsInfoHashtableNode, staticsInfoHashtableNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.StaticsInfoHashtable), staticsInfoHashtableNode); var virtualInvokeMapNode = new ReflectionVirtualInvokeMapNode(commonFixupsTableNode); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.VirtualInvokeMap), virtualInvokeMapNode, virtualInvokeMapNode, virtualInvokeMapNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.VirtualInvokeMap), virtualInvokeMapNode); var stackTraceMethodMappingNode = new StackTraceMethodMappingNode(); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.BlobIdStackTraceMethodRvaToTokenMapping), stackTraceMethodMappingNode, stackTraceMethodMappingNode, stackTraceMethodMappingNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.BlobIdStackTraceMethodRvaToTokenMapping), stackTraceMethodMappingNode); // The external references tables should go last - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.NativeReferences), nativeReferencesTableNode, nativeReferencesTableNode, nativeReferencesTableNode.EndSymbol); - header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.NativeStatics), nativeStaticsTableNode, nativeStaticsTableNode, nativeStaticsTableNode.EndSymbol); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.NativeReferences), nativeReferencesTableNode); + header.Add(BlobIdToReadyToRunSection(ReflectionMapBlob.NativeStatics), nativeStaticsTableNode); if (IsDataDehydrated) { var dehydratedDataNode = new DehydratedDataNode(); - header.Add(ReadyToRunSectionType.DehydratedData, dehydratedDataNode, dehydratedDataNode, dehydratedDataNode.EndSymbol); + header.Add(ReadyToRunSectionType.DehydratedData, dehydratedDataNode); } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RuntimeConfigurationRootProvider.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RuntimeConfigurationRootProvider.cs index 122067c0587103..de64f9eb277ce2 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RuntimeConfigurationRootProvider.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RuntimeConfigurationRootProvider.cs @@ -2,6 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Text; + +using ILCompiler.DependencyAnalysis; + +using Internal.Text; namespace ILCompiler { @@ -11,47 +16,115 @@ namespace ILCompiler /// public class RuntimeConfigurationRootProvider : ICompilationRootProvider { - private readonly IEnumerable _runtimeOptions; + private readonly string _blobName; + private readonly IReadOnlyCollection _runtimeOptions; - public RuntimeConfigurationRootProvider(IEnumerable runtimeOptions) + public RuntimeConfigurationRootProvider(string blobName, IReadOnlyCollection runtimeOptions) { + _blobName = blobName; _runtimeOptions = runtimeOptions; } void ICompilationRootProvider.AddCompilationRoots(IRootingServiceProvider rootProvider) { - rootProvider.RootReadOnlyDataBlob(GetRuntimeOptionsBlob(), 4, "Runtime configuration information", "g_compilerEmbeddedSettingsBlob"); + rootProvider.AddCompilationRoot(new RuntimeConfigurationBlobNode(_blobName, _runtimeOptions), "Runtime configuration"); } - protected byte[] GetRuntimeOptionsBlob() + private sealed class RuntimeConfigurationBlobNode : ObjectNode, ISymbolDefinitionNode { - const int HeaderSize = 4; + private readonly string _blobName; + private readonly IReadOnlyCollection _runtimeOptions; + + public RuntimeConfigurationBlobNode(string blobName, IReadOnlyCollection runtimeOptions) + { + _blobName = blobName; + _runtimeOptions = runtimeOptions; + } - ArrayBuilder options = default(ArrayBuilder); + public int Offset => 0; - // Reserve space for the header - options.ZeroExtend(HeaderSize); + public override bool IsShareable => false; - foreach (string option in _runtimeOptions) - { - byte[] optionBytes = System.Text.Encoding.ASCII.GetBytes(option); - options.Append(optionBytes); + public override int ClassCode => 7864454; - // Emit a null to separate the next option - options.Add(0); + public override bool StaticDependenciesAreComputed => true; + + public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) + { + sb.Append(_blobName); } - byte[] result = options.ToArray(); + public override ObjectNodeSection GetSection(NodeFactory factory) => + factory.Target.IsWindows ? ObjectNodeSection.ReadOnlyDataSection : ObjectNodeSection.DataSection; + + protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); + + public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) + { + var builder = new ObjectDataBuilder(factory.TypeSystemContext.Target, relocsOnly); + builder.AddSymbol(this); - int length = options.Count - HeaderSize; + var settings = new Dictionary(); - // Encode the size of the blob into the header - result[0] = (byte)length; - result[1] = (byte)(length >> 8); - result[2] = (byte)(length >> 0x10); - result[3] = (byte)(length >> 0x18); + // Put values in a dictionary - we expect many "true" strings, for example. + var valueDict = new Dictionary(); + int valueIndex = 0; + foreach (string line in _runtimeOptions) + { + int indexOfEquals = line.IndexOf("="); + if (indexOfEquals > 0) + { + string key = line.Substring(0, indexOfEquals); + string value = line.Substring(indexOfEquals + 1); - return result; + if (!valueDict.TryGetValue(value, out ISymbolNode valueNode)) + { + valueNode = factory.ReadOnlyDataBlob( + new Utf8String(_blobName + "_value_" + valueIndex++), + Utf8NullTerminatedBytes(value), + alignment: 1); + valueDict.Add(value, valueNode); + } + + settings[key] = valueNode; + } + } + + // The format is: + // * Number of entries (T) + // * N times pointer to key + // * N times pointer to value + builder.EmitNaturalInt(settings.Count); + + int i = 0; + foreach (string key in settings.Keys) + { + ISymbolNode node = factory.ReadOnlyDataBlob( + new Utf8String(_blobName + "_key_" + i++), + Utf8NullTerminatedBytes(key), + alignment: 1); + builder.EmitPointerReloc(node); + } + + foreach (ISymbolNode value in settings.Values) + { + builder.EmitPointerReloc(value); + } + + static byte[] Utf8NullTerminatedBytes(string s) + { + byte[] result = new byte[Encoding.UTF8.GetByteCount(s) + 1]; + Encoding.UTF8.GetBytes(s, result); + return result; + } + + return builder.ToObjectData(); + } + + public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) + { + return _blobName.CompareTo(((RuntimeConfigurationBlobNode)other)._blobName); + } } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RuntimeKnobsRootProvider.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RuntimeKnobsRootProvider.cs deleted file mode 100644 index db1d0236a1556e..00000000000000 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/RuntimeKnobsRootProvider.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.Collections.Generic; - -namespace ILCompiler -{ - /// - /// A root provider that provides a runtime configuration blob that influences runtime behaviors. - /// See RhConfigValues.h for allowed values. - /// - public class RuntimeKnobsRootProvider : ICompilationRootProvider - { - private readonly IEnumerable _runtimeKnobs; - - public RuntimeKnobsRootProvider(IEnumerable runtimeKnobs) - { - _runtimeKnobs = runtimeKnobs; - } - - void ICompilationRootProvider.AddCompilationRoots(IRootingServiceProvider rootProvider) - { - rootProvider.RootReadOnlyDataBlob(GetRuntimeKnobsBlob(), 4, "Runtime configuration knobs", "g_compilerEmbeddedKnobsBlob"); - } - - protected byte[] GetRuntimeKnobsBlob() - { - const int HeaderSize = 4; - - ArrayBuilder options = default(ArrayBuilder); - - // Reserve space for the header - options.ZeroExtend(HeaderSize); - - foreach (string option in _runtimeKnobs) - { - byte[] optionBytes = System.Text.Encoding.UTF8.GetBytes(option); - options.Append(optionBytes); - - // Emit a null to separate the next option - options.Add(0); - } - - byte[] result = options.ToArray(); - - int length = options.Count - HeaderSize; - - // Encode the size of the blob into the header - result[0] = (byte)length; - result[1] = (byte)(length >> 8); - result[2] = (byte)(length >> 0x10); - result[3] = (byte)(length >> 0x18); - - return result; - } - } -} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/VectorOfTFieldLayoutAlgorithm.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/VectorOfTFieldLayoutAlgorithm.cs index 1a1eef14d55820..cfa4dc2524815b 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/VectorOfTFieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/VectorOfTFieldLayoutAlgorithm.cs @@ -25,6 +25,7 @@ public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defTyp TargetDetails targetDetails = defType.Context.Target; ComputedInstanceFieldLayout layoutFromMetadata = _fallbackAlgorithm.ComputeInstanceLayout(defType, layoutKind); + layoutFromMetadata.IsVectorTOrHasVectorTFields = true; LayoutInt instanceFieldSize; @@ -53,6 +54,7 @@ public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defTyp FieldAlignment = layoutFromMetadata.FieldAlignment, FieldSize = instanceFieldSize, Offsets = layoutFromMetadata.Offsets, + IsVectorTOrHasVectorTFields = true, }; } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs index bda68c3c44d141..8ea05d0f37b189 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/ILImporter.Scanner.cs @@ -929,12 +929,32 @@ private void ImportLdToken(int token) nextBasicBlock = _basicBlocks[_currentOffset + 5]; if (nextBasicBlock == null) { + // We expect pattern: + // + // ldtoken Foo + // call GetTypeFromHandle + // ldtoken Bar + // call GetTypeFromHandle + // call Equals + // + // We check for both ldtoken cases if ((ILOpcode)_ilBytes[_currentOffset + 5] == ILOpcode.call) { methodToken = ReadILTokenAt(_currentOffset + 6); method = (MethodDesc)_methodIL.GetObject(methodToken); isTypeEquals = IsTypeEquals(method); } + else if ((ILOpcode)_ilBytes[_currentOffset + 5] == ILOpcode.ldtoken + && _basicBlocks[_currentOffset + 10] == null + && (ILOpcode)_ilBytes[_currentOffset + 10] == ILOpcode.call + && methodToken == ReadILTokenAt(_currentOffset + 11) + && _basicBlocks[_currentOffset + 15] == null + && (ILOpcode)_ilBytes[_currentOffset + 15] == ILOpcode.call) + { + methodToken = ReadILTokenAt(_currentOffset + 16); + method = (MethodDesc)_methodIL.GetObject(methodToken); + isTypeEquals = IsTypeEquals(method); + } } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/StartupCode/AppContextInitializerMethod.Sorting.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/StartupCode/AppContextInitializerMethod.Sorting.cs deleted file mode 100644 index 27d6287aef7e73..00000000000000 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/StartupCode/AppContextInitializerMethod.Sorting.cs +++ /dev/null @@ -1,21 +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 Internal.TypeSystem; - -using Debug = System.Diagnostics.Debug; - -namespace Internal.IL.Stubs.StartupCode -{ - public partial class AppContextInitializerMethod - { - protected override int ClassCode => 15749517; - - protected override int CompareToImpl(MethodDesc other, TypeSystemComparer comparer) - { - // Should be a singleton - Debug.Assert(this == other); - return 0; - } - } -} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/StartupCode/AppContextInitializerMethod.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/StartupCode/AppContextInitializerMethod.cs deleted file mode 100644 index 92d9eccdaee950..00000000000000 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/IL/Stubs/StartupCode/AppContextInitializerMethod.cs +++ /dev/null @@ -1,98 +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 Internal.TypeSystem; - -namespace Internal.IL.Stubs.StartupCode -{ - public sealed partial class AppContextInitializerMethod : ILStubMethod - { - private TypeDesc _owningType; - private MethodSignature _signature; - private IReadOnlyCollection> _switches; - - public AppContextInitializerMethod(TypeDesc owningType, IEnumerable args) - { - _owningType = owningType; - var switches = new List>(); - - foreach (string s in args) - { - int index = s.IndexOf('='); - if (index <= 0) - throw new ArgumentException($"String '{s}' in unexpected format. Expected 'Key=Value'"); - switches.Add(KeyValuePair.Create(s.Substring(0, index), s.Substring(index + 1))); - } - - _switches = switches; - } - - public override TypeSystemContext Context - { - get - { - return _owningType.Context; - } - } - - public override TypeDesc OwningType - { - get - { - return _owningType; - } - } - - public override string Name - { - get - { - return "SetAppContextSwitches"; - } - } - - public override string DiagnosticName - { - get - { - return "SetAppContextSwitches"; - } - } - - public override MethodIL EmitIL() - { - ILEmitter emitter = new ILEmitter(); - ILCodeStream codeStream = emitter.NewCodeStream(); - - MetadataType appContextType = Context.SystemModule.GetKnownType("System", "AppContext"); - MethodDesc setDataMethod = appContextType.GetKnownMethod("SetData", null); - ILToken setDataToken = emitter.NewToken(setDataMethod); - - foreach (KeyValuePair keyValue in _switches) - { - codeStream.Emit(ILOpcode.ldstr, emitter.NewToken(keyValue.Key)); - codeStream.Emit(ILOpcode.ldstr, emitter.NewToken(keyValue.Value)); - codeStream.Emit(ILOpcode.call, setDataToken); - } - - codeStream.Emit(ILOpcode.ret); - - return emitter.Link(this); - } - - public override MethodSignature Signature - { - get - { - _signature ??= new MethodSignature(MethodSignatureFlags.Static, 0, - Context.GetWellKnownType(WellKnownType.Void), - TypeDesc.EmptyTypes); - - return _signature; - } - } - } -} diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj index 724df1c41ccfcc..e0bce1b1eb82c7 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/ILCompiler.Compiler.csproj @@ -284,7 +284,6 @@ - @@ -579,7 +578,6 @@ - @@ -624,8 +622,6 @@ - - diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ArrayOfEmbeddedDataNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ArrayOfEmbeddedDataNode.cs index 36c558a19f5983..801bd7dbe2ccbd 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ArrayOfEmbeddedDataNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ArrayOfEmbeddedDataNode.cs @@ -10,24 +10,19 @@ namespace ILCompiler.DependencyAnalysis { - public interface IHasStartSymbol - { - ObjectAndOffsetSymbolNode StartSymbol { get; } - } - /// /// Represents an array of nodes. The contents of this node will be emitted /// by placing a starting symbol, followed by contents of nodes (optionally /// sorted using provided comparer), followed by ending symbol. /// - public class ArrayOfEmbeddedDataNode : EmbeddedDataContainerNode, IHasStartSymbol + public class ArrayOfEmbeddedDataNode : EmbeddedDataContainerNode where TEmbedded : EmbeddedObjectNode { private HashSet _nestedNodes = new HashSet(); private List _nestedNodesList = new List(); private IComparer _sorter; - public ArrayOfEmbeddedDataNode(string startSymbolMangledName, string endSymbolMangledName, IComparer nodeSorter) : base(startSymbolMangledName, endSymbolMangledName) + public ArrayOfEmbeddedDataNode(string mangledName, IComparer nodeSorter) : base(mangledName) { _sorter = nodeSorter; } @@ -40,11 +35,10 @@ public void AddEmbeddedObject(TEmbedded symbol) { _nestedNodesList.Add(symbol); } - symbol.ContainingNode = this; } } - protected override string GetName(NodeFactory factory) => $"Region {StartSymbol.GetMangledName(factory.NameMangler)}"; + protected override string GetName(NodeFactory factory) => $"Region {this.GetMangledName(factory.NameMangler)}"; public override ObjectNodeSection GetSection(NodeFactory factory) => ObjectNodeSection.DataSection; public override bool IsShareable => false; @@ -89,13 +83,10 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly) if (_sorter != null) _nestedNodesList.MergeSort(_sorter); - builder.AddSymbol(StartSymbol); + builder.AddSymbol(this); GetElementDataForNodes(ref builder, factory, relocsOnly); - EndSymbol.SetSymbolOffset(builder.CountBytes); - builder.AddSymbol(EndSymbol); - ObjectData objData = builder.ToObjectData(); return objData; } @@ -105,15 +96,6 @@ public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) return _nestedNodesList.Count == 0; } - protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFactory factory) - { - DependencyList dependencies = new DependencyList(); - dependencies.Add(StartSymbol, "StartSymbol"); - dependencies.Add(EndSymbol, "EndSymbol"); - - return dependencies; - } - protected internal override int Phase => (int)ObjectNodePhase.Ordered; public override int ClassCode => (int)ObjectNodeOrder.ArrayOfEmbeddedDataNode; diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs index 8fba1bae53a39c..aae7ccddd7e5fd 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ArrayOfEmbeddedPointersNode.cs @@ -30,13 +30,12 @@ public sealed class ArrayOfEmbeddedPointersNode : ArrayOfEmbeddedDataNo /// public delegate void OnMarkedDelegate(EmbeddedPointerIndirectionNode embeddedObject); - public ArrayOfEmbeddedPointersNode(string startSymbolMangledName, string endSymbolMangledName, IComparer> nodeSorter) + public ArrayOfEmbeddedPointersNode(string mangledName, IComparer> nodeSorter) : base( - startSymbolMangledName, - endSymbolMangledName, + mangledName, nodeSorter) { - _startSymbolMangledName = startSymbolMangledName; + _startSymbolMangledName = mangledName; } public EmbeddedObjectNode NewNode(TTarget target) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/EmbeddedObjectNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/EmbeddedObjectNode.cs index 511f91cbb56f22..33b7594383c49a 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/EmbeddedObjectNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/EmbeddedObjectNode.cs @@ -16,8 +16,6 @@ public abstract class EmbeddedObjectNode : SortableDependencyNode private int _offset; private int _index; - public IHasStartSymbol ContainingNode { get; set; } - public EmbeddedObjectNode() { _offset = InvalidOffset; diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionNode.cs index b0020b0ec001c7..45dc3fb4e240ab 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionNode.cs @@ -12,7 +12,7 @@ public class ImportSectionNode : EmbeddedObjectNode { private class ImportTable : ArrayOfEmbeddedDataNode { - public ImportTable(string startSymbol, string endSymbol) : base(startSymbol, endSymbol, nodeSorter: new EmbeddedObjectNodeComparer(CompilerComparer.Instance)) {} + public ImportTable(string symbol) : base(symbol, nodeSorter: new EmbeddedObjectNodeComparer(CompilerComparer.Instance)) {} public override bool ShouldSkipEmittingObjectNode(NodeFactory factory) => false; @@ -44,8 +44,8 @@ public ImportSectionNode(string name, ReadyToRunImportSectionType importType, Re _emitPrecode = emitPrecode; _emitGCRefMap = emitGCRefMap; - _imports = new ImportTable(_name + "_ImportBegin", _name + "_ImportEnd"); - _signatures = new ArrayOfEmbeddedPointersNode(_name + "_SigBegin", _name + "_SigEnd", new EmbeddedObjectNodeComparer(CompilerComparer.Instance)); + _imports = new ImportTable(_name + "_ImportBegin"); + _signatures = new ArrayOfEmbeddedPointersNode(_name + "_SigBegin", new EmbeddedObjectNodeComparer(CompilerComparer.Instance)); _signatureList = new List(); _gcRefMap = _emitGCRefMap ? new GCRefMapNode(this) : null; } @@ -101,7 +101,7 @@ public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory f { if (!_imports.ShouldSkipEmittingObjectNode(factory)) { - dataBuilder.EmitReloc(_imports.StartSymbol, RelocType.IMAGE_REL_BASED_ADDR32NB, 0); + dataBuilder.EmitReloc(_imports, RelocType.IMAGE_REL_BASED_ADDR32NB, 0); } else { @@ -110,7 +110,7 @@ public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory f if (!relocsOnly) { - dataBuilder.EmitReloc(_imports.StartSymbol, RelocType.IMAGE_REL_SYMBOL_SIZE); + dataBuilder.EmitReloc(_imports, RelocType.IMAGE_REL_SYMBOL_SIZE); dataBuilder.EmitShort((short)_flags); dataBuilder.EmitByte((byte)_type); dataBuilder.EmitByte(_entrySize); @@ -118,7 +118,7 @@ public override void EncodeData(ref ObjectDataBuilder dataBuilder, NodeFactory f if (!_signatures.ShouldSkipEmittingObjectNode(factory)) { - dataBuilder.EmitReloc(_signatures.StartSymbol, RelocType.IMAGE_REL_BASED_ADDR32NB, 0); + dataBuilder.EmitReloc(_signatures, RelocType.IMAGE_REL_BASED_ADDR32NB, 0); } else { diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionsTableNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionsTableNode.cs index 61b5e394030dce..9163ac18784d5b 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionsTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/ImportSectionsTableNode.cs @@ -12,7 +12,7 @@ public class ImportSectionsTableNode : ArrayOfEmbeddedDataNode EncodeDataCore(NodeFactory factory) yield return new GCInfoComponent(_methodNode, 0); yield return new GCInfoComponent(_methodNode, _methodNode.Size); // TODO: Is this correct? - yield return new GCInfoComponent(factory.RuntimeFunctionsGCInfo.StartSymbol, this.OffsetFromBeginningOfArray); + yield return new GCInfoComponent(factory.RuntimeFunctionsGCInfo, this.OffsetFromBeginningOfArray); } else { diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsGCInfoNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsGCInfoNode.cs index 8d69be7c2d0d34..d65a01c827a303 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsGCInfoNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsGCInfoNode.cs @@ -8,7 +8,7 @@ namespace ILCompiler.DependencyAnalysis.ReadyToRun public class RuntimeFunctionsGCInfoNode : ArrayOfEmbeddedDataNode { public RuntimeFunctionsGCInfoNode() - : base("RuntimeFunctionsGCInfo_Begin", "RuntimeFunctionsGCInfo_End", new EmbeddedObjectNodeComparer(CompilerComparer.Instance)) + : base("RuntimeFunctionsGCInfo", new EmbeddedObjectNodeComparer(CompilerComparer.Instance)) { } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsTableNode.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsTableNode.cs index 941f671c4d9a2b..d25829f7acdaa8 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsTableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/RuntimeFunctionsTableNode.cs @@ -126,7 +126,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) Debug.Assert(frameInfo.StartOffset != frameInfo.EndOffset); runtimeFunctionsBuilder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_ADDR32NB, delta: frameInfo.EndOffset); } - runtimeFunctionsBuilder.EmitReloc(factory.RuntimeFunctionsGCInfo.StartSymbol, RelocType.IMAGE_REL_BASED_ADDR32NB, funcletOffsets[frameIndex]); + runtimeFunctionsBuilder.EmitReloc(factory.RuntimeFunctionsGCInfo, RelocType.IMAGE_REL_BASED_ADDR32NB, funcletOffsets[frameIndex]); runtimeFunctionIndex++; } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs index a0b9e801f2495d..e379651ff5e2cb 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypeFixupSignature.cs @@ -36,14 +36,20 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) if (!relocsOnly) { + ReadyToRunFixupKind fixupKind = _fixupKind; dataBuilder.AddSymbol(this); + if ((fixupKind == ReadyToRunFixupKind.Verify_TypeLayout) && ((MetadataType)_typeDesc).IsVectorTOrHasVectorTFields) + { + fixupKind = ReadyToRunFixupKind.Check_TypeLayout; + } + IEcmaModule targetModule = factory.SignatureContext.GetTargetModule(_typeDesc); - SignatureContext innerContext = dataBuilder.EmitFixup(factory, _fixupKind, targetModule, factory.SignatureContext); + SignatureContext innerContext = dataBuilder.EmitFixup(factory, fixupKind, targetModule, factory.SignatureContext); dataBuilder.EmitTypeSignature(_typeDesc, innerContext); - if ((_fixupKind == ReadyToRunFixupKind.Check_TypeLayout) || - (_fixupKind == ReadyToRunFixupKind.Verify_TypeLayout)) + if ((fixupKind == ReadyToRunFixupKind.Check_TypeLayout) || + (fixupKind == ReadyToRunFixupKind.Verify_TypeLayout)) { EncodeTypeLayout(dataBuilder, _typeDesc); } @@ -92,7 +98,7 @@ private static void EncodeTypeLayout(ObjectDataSignatureBuilder dataBuilder, Typ }; dataBuilder.EmitUInt((uint)hfaElementType); } - + if (alignment != pointerSize) { dataBuilder.EmitUInt((uint)alignment); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs index 5ab12a41e6150e..14dc927fc5555d 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs @@ -742,7 +742,7 @@ public void AttachToDependencyGraph(DependencyAnalyzerBase graph, I Header.Add(Internal.Runtime.ReadyToRunSectionType.InstanceMethodEntryPoints, InstanceEntryPointTable, InstanceEntryPointTable); ImportSectionsTable = new ImportSectionsTableNode(this); - Header.Add(Internal.Runtime.ReadyToRunSectionType.ImportSections, ImportSectionsTable, ImportSectionsTable.StartSymbol); + Header.Add(Internal.Runtime.ReadyToRunSectionType.ImportSections, ImportSectionsTable, ImportSectionsTable); DebugInfoTable = new DebugInfoTableNode(); Header.Add(Internal.Runtime.ReadyToRunSectionType.DebugInfo, DebugInfoTable, DebugInfoTable); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs index 8b1b8d7c30e2e0..3644241dcf85b7 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs @@ -475,12 +475,18 @@ private bool IsLayoutFixedInCurrentVersionBubbleInternal(TypeDesc type) return true; } - if (!(type is MetadataType defType)) + if (type is not MetadataType defType) { // Non metadata backed types have layout defined in all version bubbles return true; } + if (VectorOfTFieldLayoutAlgorithm.IsVectorOfTType(defType)) + { + // Vector always needs a layout check + return false; + } + if (!NodeFactory.CompilationModuleGroup.VersionsWithModule(defType.Module)) { // Valuetypes with non-versionable attribute are candidates for fixed layout. Reject the rest. diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilerContext.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilerContext.cs index 6eed36223b0992..c6d40d4ee7b42b 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilerContext.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilerContext.cs @@ -220,6 +220,7 @@ public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, ByteCountAlignment = LayoutInt.Indeterminate, Offsets = fieldsAndOffsets.ToArray(), LayoutAbiStable = false, + IsVectorTOrHasVectorTFields = true, }; return instanceLayout; } @@ -238,6 +239,7 @@ public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, FieldSize = layoutFromSimilarIntrinsicVector.FieldSize, Offsets = layoutFromMetadata.Offsets, LayoutAbiStable = _vectorAbiIsStable, + IsVectorTOrHasVectorTFields = true, }; #else return new ComputedInstanceFieldLayout @@ -248,6 +250,7 @@ public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, FieldSize = layoutFromSimilarIntrinsicVector.FieldSize, Offsets = layoutFromMetadata.Offsets, LayoutAbiStable = _vectorAbiIsStable, + IsVectorTOrHasVectorTFields = true, }; #endif } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj index 874104ecb86821..3bb44554265c6c 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj @@ -76,7 +76,6 @@ - diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs index bb23738a4dc621..6744603dcb2288 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -3128,7 +3128,7 @@ private bool getStringChar(CORINFO_OBJECT_STRUCT_* strObj, int index, ushort* va { return false; } - + private CORINFO_OBJECT_STRUCT_* getRuntimeTypePointer(CORINFO_CLASS_STRUCT_* cls) { return null; diff --git a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILCompiler.TypeSystem.Tests.csproj b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILCompiler.TypeSystem.Tests.csproj index 1f6b33ff18ba39..d62215c7901a56 100644 --- a/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILCompiler.TypeSystem.Tests.csproj +++ b/src/coreclr/tools/aot/ILCompiler.TypeSystem.Tests/ILCompiler.TypeSystem.Tests.csproj @@ -20,7 +20,6 @@ - diff --git a/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj b/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj index 9e93415789c3c1..7e5f930584abfc 100644 --- a/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj +++ b/src/coreclr/tools/aot/ILCompiler/ILCompiler.csproj @@ -10,8 +10,10 @@ $(RuntimeBinDir)ilc-published/ - false - false + + false + + false true $(ROOTFS_DIR) true diff --git a/src/coreclr/tools/aot/ILCompiler/ILCompilerRootCommand.cs b/src/coreclr/tools/aot/ILCompiler/ILCompilerRootCommand.cs index ff80a245bcea6f..574bfb78c461ca 100644 --- a/src/coreclr/tools/aot/ILCompiler/ILCompilerRootCommand.cs +++ b/src/coreclr/tools/aot/ILCompiler/ILCompilerRootCommand.cs @@ -88,8 +88,6 @@ internal sealed class ILCompilerRootCommand : RootCommand new(new[] { "--methodbodyfolding" }, "Fold identical method bodies"); public Option InitAssemblies { get; } = new(new[] { "--initassembly" }, Array.Empty, "Assembly(ies) with a library initializer"); - public Option AppContextSwitches { get; } = - new(new[] { "--appcontextswitch" }, Array.Empty, "System.AppContext switches to set (format: 'Key=Value')"); public Option FeatureSwitches { get; } = new(new[] { "--feature" }, Array.Empty, "Feature switches to apply (format: 'Namespace.Name=[true|false]'"); public Option RuntimeOptions { get; } = @@ -114,6 +112,8 @@ internal sealed class ILCompilerRootCommand : RootCommand }, true, "Maximum number of threads to use during compilation"); public Option InstructionSet { get; } = new(new[] { "--instruction-set" }, "Instruction set to allow or disallow"); + public Option MaxVectorTBitWidth { get; } = + new(new[] { "--max-vectort-bitwidth" }, "Maximum width, in bits, that Vector is allowed to be"); public Option Guard { get; } = new(new[] { "--guard" }, "Enable mitigations. Options: 'cf': CFG (Control Flow Guard, Windows only)"); public Option Dehydrate { get; } = @@ -207,12 +207,12 @@ public ILCompilerRootCommand(string[] args) : base(".NET Native IL Compiler") AddOption(EmitStackTraceData); AddOption(MethodBodyFolding); AddOption(InitAssemblies); - AddOption(AppContextSwitches); AddOption(FeatureSwitches); AddOption(RuntimeOptions); AddOption(RuntimeKnobs); AddOption(Parallelism); AddOption(InstructionSet); + AddOption(MaxVectorTBitWidth); AddOption(Guard); AddOption(Dehydrate); AddOption(PreinitStatics); @@ -270,9 +270,11 @@ public ILCompilerRootCommand(string[] args) : base(".NET Native IL Compiler") // + the original command line arguments // + a rsp file that should work to directly run out of the zip file +#pragma warning disable CA1861 // Avoid constant arrays as arguments. Only executed once during the execution of the program. Helpers.MakeReproPackage(makeReproPath, context.ParseResult.GetValue(OutputFilePath), args, context.ParseResult, inputOptions : new[] { "r", "reference", "m", "mibc", "rdxml", "directpinvokelist", "descriptor" }, outputOptions : new[] { "o", "out", "exportsfile" }); +#pragma warning restore CA1861 // Avoid constant arrays as arguments } context.ExitCode = new Program(this).Run(); diff --git a/src/coreclr/tools/aot/ILCompiler/Program.cs b/src/coreclr/tools/aot/ILCompiler/Program.cs index 36493522a44041..f83ad617dda8d2 100644 --- a/src/coreclr/tools/aot/ILCompiler/Program.cs +++ b/src/coreclr/tools/aot/ILCompiler/Program.cs @@ -29,6 +29,7 @@ namespace ILCompiler internal sealed class Program { private readonly ILCompilerRootCommand _command; + private static readonly char[] s_separator = new char[] { ',', ';', ' ' }; public Program(ILCompilerRootCommand command) { @@ -41,7 +42,7 @@ public Program(ILCompilerRootCommand command) } } - private List CreateInitializerList(CompilerTypeSystemContext context) + private IReadOnlyCollection CreateInitializerList(CompilerTypeSystemContext context) { List assembliesWithInitializers = new List(); @@ -55,18 +56,7 @@ private List CreateInitializerList(CompilerTypeSystemContext context var libraryInitializers = new LibraryInitializers(context, assembliesWithInitializers); - List initializerList = new List(libraryInitializers.LibraryInitializerMethods); - - // If there are any AppContext switches the user wishes to enable, generate code that sets them. - string[] appContextSwitches = Get(_command.AppContextSwitches); - if (appContextSwitches.Length > 0) - { - MethodDesc appContextInitMethod = new Internal.IL.Stubs.StartupCode.AppContextInitializerMethod( - context.GeneratedAssembly.GetGlobalModuleType(), appContextSwitches); - initializerList.Add(appContextInitMethod); - } - - return initializerList; + return libraryInitializers.LibraryInitializerMethods; } public int Run() @@ -77,7 +67,7 @@ public int Run() TargetArchitecture targetArchitecture = Get(_command.TargetArchitecture); TargetOS targetOS = Get(_command.TargetOS); - InstructionSetSupport instructionSetSupport = Helpers.ConfigureInstructionSetSupport(Get(_command.InstructionSet), targetArchitecture, targetOS, + InstructionSetSupport instructionSetSupport = Helpers.ConfigureInstructionSetSupport(Get(_command.InstructionSet), Get(_command.MaxVectorTBitWidth), targetArchitecture, targetOS, "Unrecognized instruction set {0}", "Unsupported combination of instruction sets: {0}/{1}"); string systemModuleName = Get(_command.SystemModuleName); @@ -208,6 +198,8 @@ public int Run() compilationGroup = new SingleFileCompilationModuleGroup(); } + const string settingsBlobName = "g_compilerEmbeddedSettingsBlob"; + const string knobsBlobName = "g_compilerEmbeddedKnobsBlob"; string[] runtimeOptions = Get(_command.RuntimeOptions); string[] runtimeKnobs = Get(_command.RuntimeKnobs); if (nativeLib) @@ -215,8 +207,8 @@ public int Run() // Set owning module of generated native library startup method to compiler generated module, // to ensure the startup method is included in the object file during multimodule mode build compilationRoots.Add(new NativeLibraryInitializerRootProvider(typeSystemContext.GeneratedAssembly, CreateInitializerList(typeSystemContext))); - compilationRoots.Add(new RuntimeConfigurationRootProvider(runtimeOptions)); - compilationRoots.Add(new RuntimeKnobsRootProvider(runtimeKnobs)); + compilationRoots.Add(new RuntimeConfigurationRootProvider(settingsBlobName, runtimeOptions)); + compilationRoots.Add(new RuntimeConfigurationRootProvider(knobsBlobName, runtimeKnobs)); compilationRoots.Add(new ExpectedIsaFeaturesRootProvider(instructionSetSupport)); if (SplitExeInitialization) { @@ -226,8 +218,8 @@ public int Run() else if (entrypointModule != null) { compilationRoots.Add(new MainMethodRootProvider(entrypointModule, CreateInitializerList(typeSystemContext), generateLibraryAndModuleInitializers: !SplitExeInitialization)); - compilationRoots.Add(new RuntimeConfigurationRootProvider(runtimeOptions)); - compilationRoots.Add(new RuntimeKnobsRootProvider(runtimeKnobs)); + compilationRoots.Add(new RuntimeConfigurationRootProvider(settingsBlobName, runtimeOptions)); + compilationRoots.Add(new RuntimeConfigurationRootProvider(knobsBlobName, runtimeKnobs)); compilationRoots.Add(new ExpectedIsaFeaturesRootProvider(instructionSetSupport)); if (SplitExeInitialization) { @@ -691,7 +683,7 @@ private static IEnumerable ProcessWarningCodes(IEnumerable warningC { foreach (string value in warningCodes) { - string[] values = value.Split(new char[] { ',', ';', ' ' }, StringSplitOptions.RemoveEmptyEntries); + string[] values = value.Split(s_separator, StringSplitOptions.RemoveEmptyEntries); foreach (string id in values) { if (!id.StartsWith("IL", StringComparison.Ordinal) || !ushort.TryParse(id.AsSpan(2), out ushort code)) diff --git a/src/coreclr/tools/aot/ILCompiler/repro/repro.csproj b/src/coreclr/tools/aot/ILCompiler/repro/repro.csproj index 26c34d3c5d4283..131ddbd3b22576 100644 --- a/src/coreclr/tools/aot/ILCompiler/repro/repro.csproj +++ b/src/coreclr/tools/aot/ILCompiler/repro/repro.csproj @@ -23,6 +23,7 @@ + diff --git a/src/coreclr/tools/aot/crossgen2/Crossgen2RootCommand.cs b/src/coreclr/tools/aot/crossgen2/Crossgen2RootCommand.cs index e3918372e42dc9..ef384a1abece68 100644 --- a/src/coreclr/tools/aot/crossgen2/Crossgen2RootCommand.cs +++ b/src/coreclr/tools/aot/crossgen2/Crossgen2RootCommand.cs @@ -23,6 +23,8 @@ internal class Crossgen2RootCommand : RootCommand new(new[] { "--reference", "-r" }, result => Helpers.BuildPathDictionary(result.Tokens, false), true, SR.ReferenceFiles); public Option InstructionSet { get; } = new(new[] { "--instruction-set" }, SR.InstructionSets); + public Option MaxVectorTBitWidth { get; } = + new(new[] { "--max-vectort-bitwidth" }, SR.MaxVectorTBitWidths); public Option MibcFilePaths { get; } = new(new[] { "--mibc", "-m" }, Array.Empty, SR.MibcFiles); public Option OutputFilePath { get; } = @@ -193,6 +195,7 @@ public Crossgen2RootCommand(string[] args) : base(SR.Crossgen2BannerText) AddOption(UnrootedInputFilePaths); AddOption(ReferenceFilePaths); AddOption(InstructionSet); + AddOption(MaxVectorTBitWidth); AddOption(MibcFilePaths); AddOption(OutputFilePath); AddOption(CompositeRootPath); diff --git a/src/coreclr/tools/aot/crossgen2/Program.cs b/src/coreclr/tools/aot/crossgen2/Program.cs index 639e5551e96940..1d43fc8c7a9150 100644 --- a/src/coreclr/tools/aot/crossgen2/Program.cs +++ b/src/coreclr/tools/aot/crossgen2/Program.cs @@ -76,7 +76,7 @@ public int Run() TargetArchitecture targetArchitecture = Get(_command.TargetArchitecture); TargetOS targetOS = Get(_command.TargetOS); - InstructionSetSupport instructionSetSupport = Helpers.ConfigureInstructionSetSupport(Get(_command.InstructionSet), targetArchitecture, targetOS, + InstructionSetSupport instructionSetSupport = Helpers.ConfigureInstructionSetSupport(Get(_command.InstructionSet), Get(_command.MaxVectorTBitWidth), targetArchitecture, targetOS, SR.InstructionSetMustNotBe, SR.InstructionSetInvalidImplication); SharedGenericsMode genericsMode = SharedGenericsMode.CanonicalReferenceTypes; var targetDetails = new TargetDetails(targetArchitecture, targetOS, Crossgen2RootCommand.IsArmel ? TargetAbi.NativeAotArmel : TargetAbi.NativeAot, instructionSetSupport.GetVectorTSimdVector()); diff --git a/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx b/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx index b899f77a8f1147..a737ea6aeb7706 100644 --- a/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx +++ b/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx @@ -180,6 +180,9 @@ Instruction set '{0}' implies support for instruction set '{1}' + + The maximum width, in bits, for System.Numerics.Vector<T>. For example '128', '256', or '512'. + Input files without automatic rooting of all methods diff --git a/src/coreclr/tools/aot/crossgen2/crossgen2.csproj b/src/coreclr/tools/aot/crossgen2/crossgen2.csproj index 464aa2bc429075..ceeb4d63ad0c1e 100644 --- a/src/coreclr/tools/aot/crossgen2/crossgen2.csproj +++ b/src/coreclr/tools/aot/crossgen2/crossgen2.csproj @@ -8,7 +8,7 @@ false true - linux-x64;linux-musl-x64;linux-arm;linux-musl-arm;linux-arm64;linux-musl-arm64;freebsd-x64;freebsd-arm64;osx-x64;osx-arm64;win-x64;win-x86;win-arm64;win-arm + linux-x64;linux-musl-x64;linux-arm;linux-musl-arm;linux-arm64;linux-musl-arm64;freebsd-x64;freebsd-arm64;osx-x64;osx-arm64;win-x64;win-x86;win-arm64 $(PackageRID) false true diff --git a/src/coreclr/tools/dotnet-pgo/dotnet-pgo.csproj b/src/coreclr/tools/dotnet-pgo/dotnet-pgo.csproj index c3d3fc03766719..ac3720d4f7e059 100644 --- a/src/coreclr/tools/dotnet-pgo/dotnet-pgo.csproj +++ b/src/coreclr/tools/dotnet-pgo/dotnet-pgo.csproj @@ -13,7 +13,7 @@ true true dotnet-pgo - win-x64;win-x86;win-arm;osx-x64 + win-x64;win-x86;osx-x64 $(OutputPath) false .NET Performance Guided Optimization Tool diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index aa491393c414bd..70378310e449a3 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -1221,8 +1221,6 @@ const char* CorJitFlagToString(CORJIT_FLAGS::CorJitFlag flag) return "CORJIT_FLAG_BBINSTR_IF_LOOPS"; case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_PUBLISH_SECRET_PARAM: return "CORJIT_FLAG_PUBLISH_SECRET_PARAM"; - case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_SAMPLING_JIT_BACKGROUND: - return "CORJIT_FLAG_SAMPLING_JIT_BACKGROUND"; case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_USE_PINVOKE_HELPERS: return "CORJIT_FLAG_USE_PINVOKE_HELPERS"; case CORJIT_FLAGS::CorJitFlag::CORJIT_FLAG_REVERSE_PINVOKE: diff --git a/src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.cpp b/src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.cpp index d4dde380b7e236..46d05496066c7c 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/spmidumphelper.cpp @@ -259,7 +259,6 @@ std::string SpmiDumpHelper::DumpJitFlags(unsigned long long flags) AddFlag(BBINSTR_IF_LOOPS); AddFlag(PUBLISH_SECRET_PARAM); - AddFlag(SAMPLING_JIT_BACKGROUND); AddFlag(USE_PINVOKE_HELPERS); AddFlag(REVERSE_PINVOKE); AddFlag(TRACK_TRANSITIONS); diff --git a/src/coreclr/vm/CMakeLists.txt b/src/coreclr/vm/CMakeLists.txt index fada96c3a4a290..bf6b91acbf4bd4 100644 --- a/src/coreclr/vm/CMakeLists.txt +++ b/src/coreclr/vm/CMakeLists.txt @@ -578,7 +578,6 @@ if(CLR_CMAKE_TARGET_WIN32) dwreport.cpp eventreporter.cpp rtlfunctions.cpp - stacksampler.cpp ) list(APPEND VM_HEADERS_WKS @@ -587,7 +586,6 @@ if(CLR_CMAKE_TARGET_WIN32) dwreport.h eventreporter.h rtlfunctions.h - stacksampler.h ) # COM interop scenarios diff --git a/src/coreclr/vm/ClrEtwAllMeta.lst b/src/coreclr/vm/ClrEtwAllMeta.lst index 3c145a93bc1ab6..a4ea6e8a4cdb0a 100644 --- a/src/coreclr/vm/ClrEtwAllMeta.lst +++ b/src/coreclr/vm/ClrEtwAllMeta.lst @@ -190,7 +190,7 @@ nostack:Contention:::ContentionStop nomac:Contention:::ContentionStop nostack:Contention:::ContentionStop_V1 nomac:Contention:::ContentionStop_V1 -nomac:Contention:::LockCreated +nomac:Contention:::ContentionLockCreated ################## # StackWalk events diff --git a/src/coreclr/vm/array.cpp b/src/coreclr/vm/array.cpp index 54ecd0d7e7e7a3..aaa203491c5afa 100644 --- a/src/coreclr/vm/array.cpp +++ b/src/coreclr/vm/array.cpp @@ -665,7 +665,10 @@ MethodTable* Module::CreateArrayMethodTable(TypeHandle elemTypeHnd, CorElementTy IDS_CLASSLOAD_VALUECLASSTOOLARGE); } - val_serie_item *val_item = &(pSeries->val_serie[-index]); + // pSeries->val_serie is a fixed sized array. + // Use pointer arithmetic instead of direct array access to avoid compilers, specifically GCC, + // to discover undefined behavior and generate unintended code when optimization is turned on. + val_serie_item *val_item = pSeries->val_serie - index; val_item->set_val_serie_item (NumPtrs, (unsigned short)skip); } diff --git a/src/coreclr/vm/ceemain.cpp b/src/coreclr/vm/ceemain.cpp index 162c0aa7bf9cc6..1fd898684cf1c1 100644 --- a/src/coreclr/vm/ceemain.cpp +++ b/src/coreclr/vm/ceemain.cpp @@ -170,10 +170,6 @@ #include "stringarraylist.h" #include "stubhelpers.h" -#ifdef FEATURE_STACK_SAMPLING -#include "stacksampler.h" -#endif - #ifdef FEATURE_COMINTEROP #include "runtimecallablewrapper.h" #include "mngstdinterfaces.h" @@ -932,10 +928,6 @@ void EEStartupHelper() SystemDomain::System()->DefaultDomain()->SetupSharedStatics(); -#ifdef FEATURE_STACK_SAMPLING - StackSampler::Init(); -#endif - #ifdef FEATURE_MINIMETADATA_IN_TRIAGEDUMPS // retrieve configured max size for the mini-metadata buffer (defaults to 64KB) g_MiniMetaDataBuffMaxSize = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_MiniMdBufferCapacity); diff --git a/src/coreclr/vm/codeman.cpp b/src/coreclr/vm/codeman.cpp index eba0c2cd1e88fb..51eec2b9dae9a2 100644 --- a/src/coreclr/vm/codeman.cpp +++ b/src/coreclr/vm/codeman.cpp @@ -1338,6 +1338,9 @@ void EEJitManager::SetCpuInfo() CORJIT_FLAGS CPUCompileFlags; + // Get the maximum bitwidth of Vector, rounding down to the nearest multiple of 128-bits + uint32_t maxVectorTBitWidth = (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_MaxVectorTBitWidth) / 128) * 128; + #if defined(TARGET_X86) || defined(TARGET_AMD64) CPUCompileFlags.Set(InstructionSet_X86Base); @@ -1347,84 +1350,6 @@ void EEJitManager::SetCpuInfo() // AMD64 Architecture Programmer’s Manual. Volume 3 // For more information, please refer to the CPUID instruction in the respective manuals - // We will set the following flags: - // CORJIT_FLAG_USE_SSE2 is required - // SSE - EDX bit 25 - // SSE2 - EDX bit 26 - // CORJIT_FLAG_USE_AES - // CORJIT_FLAG_USE_SSE2 - // AES - ECX bit 25 - // CORJIT_FLAG_USE_PCLMULQDQ - // CORJIT_FLAG_USE_SSE2 - // PCLMULQDQ - ECX bit 1 - // CORJIT_FLAG_USE_SSE3 if the following feature bits are set (input EAX of 1) - // CORJIT_FLAG_USE_SSE2 - // SSE3 - ECX bit 0 - // CORJIT_FLAG_USE_SSSE3 if the following feature bits are set (input EAX of 1) - // CORJIT_FLAG_USE_SSE3 - // SSSE3 - ECX bit 9 - // CORJIT_FLAG_USE_SSE41 if the following feature bits are set (input EAX of 1) - // CORJIT_FLAG_USE_SSSE3 - // SSE4.1 - ECX bit 19 - // CORJIT_FLAG_USE_SSE42 if the following feature bits are set (input EAX of 1) - // CORJIT_FLAG_USE_SSE41 - // SSE4.2 - ECX bit 20 - // CORJIT_FLAG_USE_MOVBE if the following feature bits are set (input EAX of 1) - // CORJIT_FLAG_USE_SSE42 - // MOVBE - ECX bit 22 - // CORJIT_FLAG_USE_POPCNT if the following feature bits are set (input EAX of 1) - // CORJIT_FLAG_USE_SSE42 - // POPCNT - ECX bit 23 - // CORJIT_FLAG_USE_AVX if the following feature bits are set (input EAX of 1), and xmmYmmStateSupport returns 1: - // CORJIT_FLAG_USE_SSE42 - // OSXSAVE - ECX bit 27 - // AVX - ECX bit 28 - // XGETBV - XCR0[2:1] 11b - // CORJIT_FLAG_USE_FMA if the following feature bits are set (input EAX of 1), and xmmYmmStateSupport returns 1: - // CORJIT_FLAG_USE_AVX - // FMA - ECX bit 12 - // CORJIT_FLAG_USE_AVX2 if the following feature bit is set (input EAX of 0x07 and input ECX of 0): - // CORJIT_FLAG_USE_AVX - // AVX2 - EBX bit 5 - // CORJIT_FLAG_USE_AVXVNNI if the following feature bit is set (input EAX of 0x07 and input ECX of 1): - // CORJIT_FLAG_USE_AVX2 - // AVXVNNI - EAX bit 4 - // CORJIT_FLAG_USE_AVX_512F if the following feature bit is set (input EAX of 0x07 and input ECX of 0), and avx512StateSupport returns 1: - // CORJIT_FLAG_USE_AVX2 - // AVX512F - EBX bit 16 - // XGETBV - XRC0[7:5] 111b - // CORJIT_FLAG_USE_AVX_512F_VL if the following feature bit is set (input EAX of 0x07 and input ECX of 0): - // CORJIT_FLAG_USE_AVX512F - // AVX512VL - EBX bit 31 - // CORJIT_FLAG_USE_AVX_512BW if the following feature bit is set (input EAX of 0x07 and input ECX of 0): - // CORJIT_FLAG_USE_AVX512F - // AVX512BW - EBX bit 30 - // CORJIT_FLAG_USE_AVX_512BW_VL if the following feature bit is set (input EAX of 0x07 and input ECX of 0): - // CORJIT_FLAG_USE_AVX512F_VL - // CORJIT_FLAG_USE_AVX_512BW - // CORJIT_FLAG_USE_AVX_512CD if the following feature bit is set (input EAX of 0x07 and input ECX of 0): - // CORJIT_FLAG_USE_AVX512F - // AVX512CD - EBX bit 28 - // CORJIT_FLAG_USE_AVX_512CD_VL if the following feature bit is set (input EAX of 0x07 and input ECX of 0): - // CORJIT_FLAG_USE_AVX512F_VL - // CORJIT_FLAG_USE_AVX_512CD - // CORJIT_FLAG_USE_AVX_512DQ if the following feature bit is set (input EAX of 0x07 and input ECX of 0): - // CORJIT_FLAG_USE_AVX512F - // AVX512DQ - EBX bit 7 - // CORJIT_FLAG_USE_AVX_512DQ_VL if the following feature bit is set (input EAX of 0x07 and input ECX of 0): - // CORJIT_FLAG_USE_AVX512F_VL - // CORJIT_FLAG_USE_AVX_512DQ - // CORJIT_FLAG_USE_AVX_512VBMI if the following feature bit is set (input EAX of 0x07 and input ECX of 0): - // CORJIT_FLAG_USE_AVX512F - // AVX512VBMI - ECX bit 1 - // CORJIT_FLAG_USE_BMI1 if the following feature bit is set (input EAX of 0x07 and input ECX of 0): - // BMI1 - EBX bit 3 - // CORJIT_FLAG_USE_BMI2 if the following feature bit is set (input EAX of 0x07 and input ECX of 0): - // BMI2 - EBX bit 8 - // CORJIT_FLAG_USE_LZCNT if the following feature bits are set (input EAX of 80000001H) - // LZCNT - ECX bit 5 - // synchronously updating VM and JIT. - union XarchCpuInfo { struct { @@ -1479,6 +1404,7 @@ void EEJitManager::SetCpuInfo() CPUCompileFlags.Set(InstructionSet_SSE); CPUCompileFlags.Set(InstructionSet_SSE2); + CPUCompileFlags.Set(InstructionSet_VectorT128); if ((cpuidInfo[CPUID_ECX] & (1 << 25)) != 0) // AESNI { @@ -1516,9 +1442,12 @@ void EEJitManager::SetCpuInfo() CPUCompileFlags.Set(InstructionSet_POPCNT); } - if (((cpuidInfo[CPUID_ECX] & (1 << 27)) != 0) && ((cpuidInfo[CPUID_ECX] & (1 << 28)) != 0)) // OSXSAVE & AVX + const int requiredAvxEcxFlags = (1 << 27) // OSXSAVE + | (1 << 28); // AVX + + if ((cpuidInfo[CPUID_ECX] & requiredAvxEcxFlags) == requiredAvxEcxFlags) { - if(DoesOSSupportAVX() && (xmmYmmStateSupport() == 1)) // XGETBV == 11 + if(DoesOSSupportAVX() && (xmmYmmStateSupport() == 1)) // XGETBV == 11 { CPUCompileFlags.Set(InstructionSet_AVX); @@ -1535,50 +1464,60 @@ void EEJitManager::SetCpuInfo() { CPUCompileFlags.Set(InstructionSet_AVX2); - if (DoesOSSupportAVX512() && (avx512StateSupport() == 1)) // XGETBV XRC0[7:5] == 111 + if ((maxVectorTBitWidth == 0) || (maxVectorTBitWidth >= 256)) + { + // We allow 256-bit Vector by default + CPUCompileFlags.Clear(InstructionSet_VectorT128); + CPUCompileFlags.Set(InstructionSet_VectorT256); + } + + if (DoesOSSupportAVX512() && (avx512StateSupport() == 1)) // XGETBV XRC0[7:5] == 111 { - if ((cpuidInfo[CPUID_EBX] & (1 << 16)) != 0) // AVX512F + if ((cpuidInfo[CPUID_EBX] & (1 << 16)) != 0) // AVX512F { CPUCompileFlags.Set(InstructionSet_AVX512F); + // TODO-XArch: Add support for 512-bit Vector + assert(!CPUCompileFlags.IsSet(InstructionSet_VectorT512)); + bool isAVX512_VLSupported = false; - if ((cpuidInfo[CPUID_EBX] & (1 << 31)) != 0) // AVX512VL + if ((cpuidInfo[CPUID_EBX] & (1 << 31)) != 0) // AVX512VL { CPUCompileFlags.Set(InstructionSet_AVX512F_VL); isAVX512_VLSupported = true; } - if ((cpuidInfo[CPUID_EBX] & (1 << 30)) != 0) // AVX512BW + if ((cpuidInfo[CPUID_EBX] & (1 << 30)) != 0) // AVX512BW { CPUCompileFlags.Set(InstructionSet_AVX512BW); - if (isAVX512_VLSupported) // AVX512BW_VL + if (isAVX512_VLSupported) // AVX512BW_VL { CPUCompileFlags.Set(InstructionSet_AVX512BW_VL); } } - if ((cpuidInfo[CPUID_EBX] & (1 << 28)) != 0) // AVX512CD + if ((cpuidInfo[CPUID_EBX] & (1 << 28)) != 0) // AVX512CD { CPUCompileFlags.Set(InstructionSet_AVX512CD); - if (isAVX512_VLSupported) // AVX512CD_VL + if (isAVX512_VLSupported) // AVX512CD_VL { CPUCompileFlags.Set(InstructionSet_AVX512CD_VL); } } - if ((cpuidInfo[CPUID_EBX] & (1 << 17)) != 0) // AVX512DQ + if ((cpuidInfo[CPUID_EBX] & (1 << 17)) != 0) // AVX512DQ { CPUCompileFlags.Set(InstructionSet_AVX512DQ); - if (isAVX512_VLSupported) // AVX512DQ_VL + if (isAVX512_VLSupported) // AVX512DQ_VL { CPUCompileFlags.Set(InstructionSet_AVX512DQ_VL); } } - if ((cpuidInfo[CPUID_ECX] & (1 << 1)) != 0) // AVX512VBMI + if ((cpuidInfo[CPUID_ECX] & (1 << 1)) != 0) // AVX512VBMI { CPUCompileFlags.Set(InstructionSet_AVX512VBMI); - if (isAVX512_VLSupported) // AVX512VBMI_VL + if (isAVX512_VLSupported) // AVX512VBMI_VL { CPUCompileFlags.Set(InstructionSet_AVX512VBMI_VL); } @@ -1601,28 +1540,23 @@ void EEJitManager::SetCpuInfo() } } - if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_SIMD16ByteOnly) != 0) - { - CPUCompileFlags.Clear(InstructionSet_AVX2); - } - if (maxCpuId >= 0x07) { __cpuidex(cpuidInfo, 0x00000007, 0x00000000); - if ((cpuidInfo[CPUID_EBX] & (1 << 3)) != 0) // BMI1 + if ((cpuidInfo[CPUID_EBX] & (1 << 3)) != 0) // BMI1 { CPUCompileFlags.Set(InstructionSet_BMI1); } - if ((cpuidInfo[CPUID_EBX] & (1 << 8)) != 0) // BMI2 + if ((cpuidInfo[CPUID_EBX] & (1 << 8)) != 0) // BMI2 { CPUCompileFlags.Set(InstructionSet_BMI2); } if ((cpuidInfo[CPUID_EDX] & (1 << 14)) != 0) { - CPUCompileFlags.Set(InstructionSet_X86Serialize); // SERIALIZE + CPUCompileFlags.Set(InstructionSet_X86Serialize); // SERIALIZE } } @@ -1633,7 +1567,7 @@ void EEJitManager::SetCpuInfo() { __cpuid(cpuidInfo, 0x80000001); - if ((cpuidInfo[CPUID_ECX] & (1 << 5)) != 0) // LZCNT + if ((cpuidInfo[CPUID_ECX] & (1 << 5)) != 0) // LZCNT { CPUCompileFlags.Set(InstructionSet_LZCNT); } @@ -1656,6 +1590,7 @@ void EEJitManager::SetCpuInfo() // FP and SIMD support are enabled by default CPUCompileFlags.Set(InstructionSet_ArmBase); CPUCompileFlags.Set(InstructionSet_AdvSimd); + CPUCompileFlags.Set(InstructionSet_VectorT128); // PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE (30) if (IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE)) @@ -1867,7 +1802,6 @@ void EEJitManager::SetCpuInfo() { CPUCompileFlags.Clear(InstructionSet_X86Serialize); } - #elif defined(TARGET_ARM64) if (!CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_EnableHWIntrinsic)) { diff --git a/src/coreclr/vm/comutilnative.cpp b/src/coreclr/vm/comutilnative.cpp index 6d457a40248503..f2985222815e20 100644 --- a/src/coreclr/vm/comutilnative.cpp +++ b/src/coreclr/vm/comutilnative.cpp @@ -1523,59 +1523,6 @@ FCIMPL3_IVV(INT64, COMInterlocked::CompareExchange64, INT64* location, INT64 val } FCIMPLEND -FCIMPL2_IV(float,COMInterlocked::ExchangeFloat, float *location, float value) -{ - FCALL_CONTRACT; - - if( NULL == location) { - FCThrow(kNullReferenceException); - } - - LONG ret = InterlockedExchange((LONG *) location, *(LONG*)&value); - return *(float*)&ret; -} -FCIMPLEND - -FCIMPL2_IV(double,COMInterlocked::ExchangeDouble, double *location, double value) -{ - FCALL_CONTRACT; - - if( NULL == location) { - FCThrow(kNullReferenceException); - } - - - INT64 ret = InterlockedExchange64((INT64 *) location, *(INT64*)&value); - return *(double*)&ret; -} -FCIMPLEND - -FCIMPL3_IVV(float,COMInterlocked::CompareExchangeFloat, float *location, float value, float comparand) -{ - FCALL_CONTRACT; - - if( NULL == location) { - FCThrow(kNullReferenceException); - } - - LONG ret = (LONG)InterlockedCompareExchange((LONG*) location, *(LONG*)&value, *(LONG*)&comparand); - return *(float*)&ret; -} -FCIMPLEND - -FCIMPL3_IVV(double,COMInterlocked::CompareExchangeDouble, double *location, double value, double comparand) -{ - FCALL_CONTRACT; - - if( NULL == location) { - FCThrow(kNullReferenceException); - } - - INT64 ret = (INT64)InterlockedCompareExchange64((INT64*) location, *(INT64*)&value, *(INT64*)&comparand); - return *(double*)&ret; -} -FCIMPLEND - FCIMPL2(LPVOID,COMInterlocked::ExchangeObject, LPVOID*location, LPVOID value) { FCALL_CONTRACT; @@ -1637,24 +1584,6 @@ FCIMPL2_IV(INT64,COMInterlocked::ExchangeAdd64, INT64 *location, INT64 value) } FCIMPLEND -FCIMPL0(void, COMInterlocked::FCMemoryBarrier) -{ - FCALL_CONTRACT; - - MemoryBarrier(); - FC_GC_POLL(); -} -FCIMPLEND - -FCIMPL0(void, COMInterlocked::FCMemoryBarrierLoad) -{ - FCALL_CONTRACT; - - VolatileLoadBarrier(); - FC_GC_POLL(); -} -FCIMPLEND - #include extern "C" void QCALLTYPE Interlocked_MemoryBarrierProcessWide() diff --git a/src/coreclr/vm/comutilnative.h b/src/coreclr/vm/comutilnative.h index 0d6d3f8a5f95fe..37e19a14f6ec3a 100644 --- a/src/coreclr/vm/comutilnative.h +++ b/src/coreclr/vm/comutilnative.h @@ -227,17 +227,10 @@ class COMInterlocked static FCDECL2_IV(INT64, Exchange64, INT64 *location, INT64 value); static FCDECL3(INT32, CompareExchange, INT32* location, INT32 value, INT32 comparand); static FCDECL3_IVV(INT64, CompareExchange64, INT64* location, INT64 value, INT64 comparand); - static FCDECL2_IV(float, ExchangeFloat, float *location, float value); - static FCDECL2_IV(double, ExchangeDouble, double *location, double value); - static FCDECL3_IVV(float, CompareExchangeFloat, float *location, float value, float comparand); - static FCDECL3_IVV(double, CompareExchangeDouble, double *location, double value, double comparand); static FCDECL2(LPVOID, ExchangeObject, LPVOID* location, LPVOID value); static FCDECL3(LPVOID, CompareExchangeObject, LPVOID* location, LPVOID value, LPVOID comparand); static FCDECL2(INT32, ExchangeAdd32, INT32 *location, INT32 value); static FCDECL2_IV(INT64, ExchangeAdd64, INT64 *location, INT64 value); - - static FCDECL0(void, FCMemoryBarrier); - static FCDECL0(void, FCMemoryBarrierLoad); }; extern "C" void QCALLTYPE Interlocked_MemoryBarrierProcessWide(); diff --git a/src/coreclr/vm/ecalllist.h b/src/coreclr/vm/ecalllist.h index acda36bace331d..9fc399c31cd5a3 100644 --- a/src/coreclr/vm/ecalllist.h +++ b/src/coreclr/vm/ecalllist.h @@ -509,18 +509,12 @@ FCFuncEnd() FCFuncStart(gInterlockedFuncs) FCFuncElementSig("Exchange", &gsig_SM_RefInt_Int_RetInt, COMInterlocked::Exchange) FCFuncElementSig("Exchange", &gsig_SM_RefLong_Long_RetLong, COMInterlocked::Exchange64) - FCFuncElementSig("Exchange", &gsig_SM_RefDbl_Dbl_RetDbl, COMInterlocked::ExchangeDouble) - FCFuncElementSig("Exchange", &gsig_SM_RefFlt_Flt_RetFlt, COMInterlocked::ExchangeFloat) FCFuncElementSig("Exchange", &gsig_SM_RefObj_Obj_RetObj, COMInterlocked::ExchangeObject) FCFuncElementSig("CompareExchange", &gsig_SM_RefInt_Int_Int_RetInt, COMInterlocked::CompareExchange) FCFuncElementSig("CompareExchange", &gsig_SM_RefLong_Long_Long_RetLong, COMInterlocked::CompareExchange64) - FCFuncElementSig("CompareExchange", &gsig_SM_RefDbl_Dbl_Dbl_RetDbl, COMInterlocked::CompareExchangeDouble) - FCFuncElementSig("CompareExchange", &gsig_SM_RefFlt_Flt_Flt_RetFlt, COMInterlocked::CompareExchangeFloat) FCFuncElementSig("CompareExchange", &gsig_SM_RefObj_Obj_Obj_RetObj, COMInterlocked::CompareExchangeObject) FCFuncElementSig("ExchangeAdd", &gsig_SM_RefInt_Int_RetInt, COMInterlocked::ExchangeAdd32) FCFuncElementSig("ExchangeAdd", &gsig_SM_RefLong_Long_RetLong, COMInterlocked::ExchangeAdd64) - FCFuncElement("MemoryBarrier", COMInterlocked::FCMemoryBarrier) - FCFuncElement("ReadMemoryBarrier", COMInterlocked::FCMemoryBarrierLoad) FCFuncEnd() FCFuncStart(gJitInfoFuncs) diff --git a/src/coreclr/vm/i386/stublinkerx86.cpp b/src/coreclr/vm/i386/stublinkerx86.cpp index 3203e4f4ce3717..fde6801c289b6d 100644 --- a/src/coreclr/vm/i386/stublinkerx86.cpp +++ b/src/coreclr/vm/i386/stublinkerx86.cpp @@ -4558,8 +4558,8 @@ VOID StubLinkerCPU::EmitArrayOpStub(const ArrayOpScript* pArrayOpScript) for (SSIZE_T __i = 0; __i > cnt; __i--) { - HALF_SIZE_T skip = cur->val_serie[__i].skip; - HALF_SIZE_T nptrs = cur->val_serie[__i].nptrs; + HALF_SIZE_T skip = (cur->val_serie + __i)->skip; + HALF_SIZE_T nptrs = (cur->val_serie + __i)->nptrs; total += nptrs*sizeof (Object*); do { diff --git a/src/coreclr/vm/interoputil.cpp b/src/coreclr/vm/interoputil.cpp index 65710a5227be54..d2dc577b30cf71 100644 --- a/src/coreclr/vm/interoputil.cpp +++ b/src/coreclr/vm/interoputil.cpp @@ -3114,7 +3114,7 @@ void IUInvokeDispMethod( // Validate that the target is valid for the specified type. if (!IsComTargetValidForType(pRefClassObj, pTarget)) - COMPlusThrow(kTargetException, W("RFLCT.Targ_ITargMismatch")); + COMPlusThrow(kTargetException, W("RFLCT_Targ_ITargMismatch")); // If the invoked type is an interface, make sure it is IDispatch based. if (pInvokedMT->IsInterface()) diff --git a/src/coreclr/vm/invokeutil.cpp b/src/coreclr/vm/invokeutil.cpp index ea2278e73e37c4..c4ba804a4c493f 100644 --- a/src/coreclr/vm/invokeutil.cpp +++ b/src/coreclr/vm/invokeutil.cpp @@ -681,7 +681,7 @@ void InvokeUtil::ValidateObjectTarget(FieldDesc *pField, TypeHandle enclosingTyp return; if (!pField->IsStatic() && !*target) - COMPlusThrow(kTargetException,W("RFLCT.Targ_StatFldReqTarg")); + COMPlusThrow(kTargetException,W("RFLCT_Targ_StatFldReqTarg")); // Verify that the object is of the proper type... TypeHandle ty = (*target)->GetTypeHandle(); diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index 85d904b566cdd5..15365a90216a84 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -1800,7 +1800,7 @@ uint32_t CEEInfo::getThreadLocalFieldInfo (CORINFO_FIELD_HANDLE field, bool isG } assert(typeIndex != TypeIDProvider::INVALID_TYPE_ID); - + EE_TO_JIT_TRANSITION(); return typeIndex; } @@ -1830,9 +1830,9 @@ void CEEInfo::getThreadLocalStaticBlocksInfo (CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo->offsetOfThreadStaticBlocks = CEEInfo::ThreadLocalOffset(&t_NonGCThreadStaticBlocks); pInfo->offsetOfMaxThreadStaticBlocks = CEEInfo::ThreadLocalOffset(&t_NonGCMaxThreadStaticBlocks); } - + pInfo->offsetOfGCDataPointer = static_cast(PtrArray::GetDataOffset()); - + JIT_TO_EE_TRANSITION_LEAF(); } #else @@ -1864,7 +1864,7 @@ void CEEInfo::getThreadLocalStaticBlocksInfo (CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo->offsetOfThreadStaticBlocks = 0; pInfo->offsetOfMaxThreadStaticBlocks = 0; pInfo->offsetOfGCDataPointer = 0; - + JIT_TO_EE_TRANSITION_LEAF(); } #endif // HOST_WINDOWS @@ -12453,17 +12453,8 @@ CorJitResult invokeCompileMethodHelper(EEJitManager *jitMgr, CorJitResult ret = CORJIT_SKIPPED; // Note that CORJIT_SKIPPED is an error exit status code -#ifdef FEATURE_STACK_SAMPLING - static ConfigDWORD s_stackSamplingEnabled; - bool samplingEnabled = (s_stackSamplingEnabled.val(CLRConfig::UNSUPPORTED_StackSamplingEnabled) != 0); -#endif - #if defined(ALLOW_SXS_JIT) - if (FAILED(ret) && jitMgr->m_alternateJit -#ifdef FEATURE_STACK_SAMPLING - && (!samplingEnabled || (jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SAMPLING_JIT_BACKGROUND))) -#endif - ) + if (FAILED(ret) && jitMgr->m_alternateJit) { CORJIT_FLAGS altJitFlags = jitFlags; altJitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_ALT_JIT); @@ -12474,14 +12465,6 @@ CorJitResult invokeCompileMethodHelper(EEJitManager *jitMgr, nativeEntry, nativeSizeOfCode); -#ifdef FEATURE_STACK_SAMPLING - if (jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SAMPLING_JIT_BACKGROUND)) - { - // Don't bother with failures if we couldn't collect a trace. - ret = CORJIT_OK; - } -#endif // FEATURE_STACK_SAMPLING - // If we failed to jit, then fall back to the primary Jit. if (FAILED(ret)) { @@ -13099,14 +13082,7 @@ PCODE UnsafeJitFunction(PrepareCodeConfig* config, { jitInfo.WriteCode(jitMgr); #if defined(DEBUGGING_SUPPORTED) - // Note: if we're only importing (ie, verifying/ - // checking to make sure we could JIT, but not actually generating code ( - // eg, for inlining), then DON'T TELL THE DEBUGGER about this. - if (!flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_MCJIT_BACKGROUND) -#ifdef FEATURE_STACK_SAMPLING - && !flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SAMPLING_JIT_BACKGROUND) -#endif // FEATURE_STACK_SAMPLING - ) + if (!flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_MCJIT_BACKGROUND)) { // // Notify the debugger that we have successfully jitted the function diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 0349ca2684e990..45c585da6d2196 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -1135,6 +1135,7 @@ BOOL MethodTableBuilder::CheckIfSIMDAndUpdateSize() LPCUTF8 className; LPCUTF8 nameSpace; + if (FAILED(GetMDImport()->GetNameOfTypeDef(bmtInternal->pType->GetTypeDefToken(), &className, &nameSpace))) return false; @@ -1144,7 +1145,12 @@ BOOL MethodTableBuilder::CheckIfSIMDAndUpdateSize() CORJIT_FLAGS CPUCompileFlags = ExecutionManager::GetEEJitManager()->GetCPUCompileFlags(); uint32_t numInstanceFieldBytes = 16; - if (CPUCompileFlags.IsSet(InstructionSet_AVX2)) + if (CPUCompileFlags.IsSet(InstructionSet_VectorT512)) + { + // TODO-XARCH: The JIT needs to be updated to support 64-byte Vector + numInstanceFieldBytes = 32; + } + else if (CPUCompileFlags.IsSet(InstructionSet_VectorT256)) { numInstanceFieldBytes = 32; } diff --git a/src/coreclr/vm/prestub.cpp b/src/coreclr/vm/prestub.cpp index 29965fd0477a28..e555da0436607b 100644 --- a/src/coreclr/vm/prestub.cpp +++ b/src/coreclr/vm/prestub.cpp @@ -30,10 +30,6 @@ #include "clrtocomcall.h" #endif -#ifdef FEATURE_STACK_SAMPLING -#include "stacksampler.h" -#endif - #ifdef FEATURE_PERFMAP #include "perfmap.h" #endif @@ -858,10 +854,6 @@ PCODE MethodDesc::JitCompileCodeLockedEventWrapper(PrepareCodeConfig* pConfig, J } -#ifdef FEATURE_STACK_SAMPLING - StackSampler::RecordJittingInfo(this, flags); -#endif // FEATURE_STACK_SAMPLING - #ifdef PROFILING_SUPPORTED { BEGIN_PROFILER_CALLBACK(CORProfilerTrackJITInfo()); diff --git a/src/coreclr/vm/riscv64/stubs.cpp b/src/coreclr/vm/riscv64/stubs.cpp index 4c40d61acb26e2..612462e0184720 100644 --- a/src/coreclr/vm/riscv64/stubs.cpp +++ b/src/coreclr/vm/riscv64/stubs.cpp @@ -914,7 +914,7 @@ UMEntryThunk * UMEntryThunk::Decode(void *pCallback) // stubs (see UMEntryThunkCode::Encode below) then we'll return NULL. Luckily in these scenarios our // caller will perform a hash lookup on successful return to verify our result in case random unmanaged // code happens to look like ours. - if ((pCode->m_code[0] == 0x00009f97) && // auipc t6, 0 + if ((pCode->m_code[0] == 0x00000f97) && // auipc t6, 0 (pCode->m_code[1] == 0x018fb383) && // ld t2, 24(t6) (pCode->m_code[2] == 0x010fbf83) && // ld t6, 16(t6) (pCode->m_code[3] == 0x000f8067)) // jalr x0, 0(t6) @@ -934,7 +934,7 @@ void UMEntryThunkCode::Encode(UMEntryThunkCode *pEntryThunkCodeRX, BYTE* pTarget // m_pTargetCode data // m_pvSecretParam data - m_code[0] = 0x00009f97; // auipc t6, 0 + m_code[0] = 0x00000f97; // auipc t6, 0 m_code[1] = 0x018fb383; // ld t2, 24(t6) m_code[2] = 0x010fbf83; // ld t6, 16(t6) m_code[3] = 0x000f8067; // jalr x0, 0(t6) diff --git a/src/coreclr/vm/riscv64/virtualcallstubcpu.hpp b/src/coreclr/vm/riscv64/virtualcallstubcpu.hpp index 6edfec858bbd88..53a3c2c0ac9187 100644 --- a/src/coreclr/vm/riscv64/virtualcallstubcpu.hpp +++ b/src/coreclr/vm/riscv64/virtualcallstubcpu.hpp @@ -44,7 +44,7 @@ struct LookupHolder // _resolveWorkerTarget // _token - _stub._entryPoint[0] = LOOKUP_STUB_FIRST_DWORD; // auipc t6, 0 //0x00000097 + _stub._entryPoint[0] = LOOKUP_STUB_FIRST_DWORD; // auipc t6, 0 //0x00000f97 _stub._entryPoint[1] = 0x018fb383; //ld t2, 24(t6) _stub._entryPoint[2] = 0x010fbf83; //ld t6, 16(t6) _stub._entryPoint[3] = 0x000f8067; //jalr x0, t6, 0 @@ -226,7 +226,7 @@ struct ResolveHolder _stub._resolveEntryPoint[n++] = 0x005e0333; // auipc t0, 0 _stub._resolveEntryPoint[n++] = 0x00000297; - // addi t0, t0, -16 + // addi t0, t0, -12 _stub._resolveEntryPoint[n++] = 0xff428293; // lw t6, 0(t0) #t6 = this._hashedToken @@ -461,7 +461,7 @@ void VTableCallHolder::Initialize(unsigned slot) *(DWORD*)p = 0x00036e03 | ((UINT32)dataOffset << 20); p += 4; // add t4, t4, t3 *(DWORD*)p = 0x01ce8eb3; p += 4; - // ld t4, offsetOfIndirection(t4) + // ld t4, 0(t4) *(DWORD*)p = 0x000ebe83; p += 4; } else @@ -485,7 +485,7 @@ void VTableCallHolder::Initialize(unsigned slot) } else { - // ld t4, offsetOfIndirection(t4) + // ld t4, offsetAfterIndirection(t4) *(DWORD*)p = 0x000ebe83 | ((UINT32)offsetAfterIndirection << 20); p += 4; } diff --git a/src/coreclr/vm/stackingallocator.h b/src/coreclr/vm/stackingallocator.h index a937bf942201a3..2753de73908b42 100644 --- a/src/coreclr/vm/stackingallocator.h +++ b/src/coreclr/vm/stackingallocator.h @@ -227,7 +227,7 @@ private : Thread *pThread__ACQUIRE_STACKING_ALLOCATOR = GetThread(); \ StackingAllocator *stackingAllocatorName = pThread__ACQUIRE_STACKING_ALLOCATOR->m_stackLocalAllocator; \ bool allocatorOwner__ACQUIRE_STACKING_ALLOCATOR = false; \ - NewHolder heapAllocatedStackingBuffer__ACQUIRE_STACKING_ALLOCATOR; \ + NewArrayHolder heapAllocatedStackingBuffer__ACQUIRE_STACKING_ALLOCATOR; \ \ if (stackingAllocatorName == NULL) \ { \ @@ -237,10 +237,11 @@ private : } \ else \ {\ - stackingAllocatorName = new (nothrow) StackingAllocator; \ - if (stackingAllocatorName == NULL) \ + char *pBuffer__ACQUIRE_STACKING_ALLOCATOR = new (nothrow) char[sizeof(StackingAllocator)]; \ + if (pBuffer__ACQUIRE_STACKING_ALLOCATOR == NULL) \ ThrowOutOfMemory(); \ - heapAllocatedStackingBuffer__ACQUIRE_STACKING_ALLOCATOR = stackingAllocatorName; \ + heapAllocatedStackingBuffer__ACQUIRE_STACKING_ALLOCATOR = pBuffer__ACQUIRE_STACKING_ALLOCATOR; \ + stackingAllocatorName = new (pBuffer__ACQUIRE_STACKING_ALLOCATOR) StackingAllocator; \ }\ allocatorOwner__ACQUIRE_STACKING_ALLOCATOR = true; \ } \ diff --git a/src/coreclr/vm/stacksampler.cpp b/src/coreclr/vm/stacksampler.cpp deleted file mode 100644 index f49218e8590483..00000000000000 --- a/src/coreclr/vm/stacksampler.cpp +++ /dev/null @@ -1,433 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// -// Summary: -// -------- -// -// StackSampler is intended to identify methods where the process is spending most of its time -// and to re-JIT such methods in the background. Call these methods hot. -// -// Identifying hot methods: -// ======================== -// -// There is no easy way to tell at a given point in execution whether in the future an unseen -// or un-hot method will become hot; So we track an evolving list of hot methods. -// -// We identify hot methods by suspending the runtime every "m" milliseconds. This operation -// freezes all the threads. We now get a list of threads that are executing and walk their -// stacks to get the managed method at the top of their stacks. The sampled list of methods -// for each thread constitute a single sample. Once we obtain a sample, the threads are thawed. -// -// The more a method is present in samples, it is clear that the process is spending its time -// in that method at several given points in time. -// -// We track this information on a per method basis, the count of its occurrences in each sample -// using a hash map. -// -// Note: -// ===== -// o Using the above technique we have only identified top methods at a given point in the execution. -// The list of hot methods keeps evolving as we get more samples. Only at the process end can we -// say that the evolving list of hot methods is THE list of hot methods for the whole process. -// o Because we get the top managed method in the thread, this includes time spent by that method -// in helper calls. -// o If GC is in progress it has suspended the threads, and we would not be able to suspend the threads. -// -// Future Consideration: -// ===================== -// We could track "trending" methods, as methods decay out so we can keep only "trending" variants -// in the code manager and kick out "past" hot methods. -// -// Jitting in the background: -// ========================== -// Once we have the hot methods at a given point in time, we JIT them. The decision to JIT is configurable -// by configuring the number of times a method is seen in samples before we would JIT it. -// For example, if we are sampling every 10 msec and if we expect methods that spend at least 1 second -// to be hot, then the number of times to see this method is roughly, 100, it is best to be conservative -// with this number. -// -// Note that we JIT the evolving list of methods, without knowing ahead of time that the methods we JIT -// will be the final top "n" hot methods due to the lack of knowledge of when the process will end. -// This means we would over-JIT but this only yields results with false negatives. -// -// Currently we JIT in the background only once (with the current goal of getting a trace.) -// -// Note: -// ===== -// o To run the JIT in the background, we try our best to JIT in the same app domain in which the original -// JITting happened. But if we fail to acquire (ngen'ed method) or enter (unloaded domain) the original domain, -// we then try to JIT it under the thread's app domain in which the method was last seen to be executing. -// -// o The JIT to use is configurable with DOTNET_AltJitName when DOTNET_StackSampling is enabled. -// -// o One use case is to collect traces as an .mc file from SuperPMI Shim JIT. -// -// Jitting parameters: -// ========================== -// The prestub tells us at JITting time using "RecordJittingInfo" to record the parameters used to JIT -// originally. We use these parameters to JIT in the background when we decide to JIT the method. -// - - -#include "common.h" -#include "corjit.h" -#include "stacksampler.h" -#include "threadsuspend.h" - -#ifdef FEATURE_STACK_SAMPLING - -// Global instance of the sampler -StackSampler* g_pStackSampler = nullptr; - -// Create an instance of the stack sampler if sampling is enabled. -void StackSampler::Init() -{ - STANDARD_VM_CONTRACT; - - bool samplingEnabled = (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_StackSamplingEnabled) != 0); - if (samplingEnabled) - { - g_pStackSampler = new (nothrow) StackSampler(); - } -} - -// ThreadProc for performing sampling and JITting. -/* static */ -DWORD __stdcall StackSampler::SamplingThreadProc(void* arg) -{ - WRAPPER_NO_CONTRACT; - - StackSampler* pThis = (StackSampler*) arg; - pThis->ThreadProc(); - return 0; -} - -// Constructor -StackSampler::StackSampler() - : m_crstJitInfo(CrstStackSampler, (CrstFlags)(CRST_UNSAFE_ANYMODE)) - , m_nSampleEvery(s_knDefaultSamplingIntervalMsec) - , m_nSampleAfter(0) - , m_nNumMethods(s_knDefaultNumMethods) -{ - // When to start sampling after the thread launch. - int nSampleAfter = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_StackSamplingAfter); - if (nSampleAfter != INT_MAX && nSampleAfter >= 0) - { - m_nSampleAfter = nSampleAfter; - } - - // How frequently to sample. - int nSampleEvery = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_StackSamplingEvery); - if (nSampleEvery != INT_MAX && nSampleEvery > 0) - { - m_nSampleEvery = nSampleEvery; - } - - // Max number of methods to track. - int nNumMethods = CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_StackSamplingNumMethods); - if (nNumMethods != INT_MAX && nNumMethods > 0) - { - m_nNumMethods = nNumMethods; - } - - // Launch the thread. - m_pThread = SetupUnstartedThread(); - m_pThread->SetBackground(TRUE); - - // Passing "this" to the thread in the constructor. - if (m_pThread->CreateNewThread(1*1024*1024, SamplingThreadProc, this)) - { - m_pThread->StartThread(); - } -} - -// Is "pMD" a good method, that is suitable for tracking as HOT and -// JITting in the background. -bool IsGoodMethodDesc(MethodDesc* pMD) -{ - LIMITED_METHOD_CONTRACT; - return !(pMD == nullptr || !pMD->IsIL() || pMD->IsUnboxingStub() || pMD->GetMethodTable()->Collectible()); -} - -// -// An opportunity to record the parameters passed to the JIT at the time of JITting this method. -/* static */ -void StackSampler::RecordJittingInfo(MethodDesc* pMD, CORJIT_FLAGS flags) -{ - WRAPPER_NO_CONTRACT; - if (g_pStackSampler == nullptr) - { - return; - } - // Skip if this is not a good method desc. - if (!IsGoodMethodDesc(pMD)) - { - return; - } - // Record in the hash map. - g_pStackSampler->RecordJittingInfoInternal(pMD, flags); -} - -void StackSampler::RecordJittingInfoInternal(MethodDesc* pMD, CORJIT_FLAGS flags) -{ - JitInfoHashEntry entry(pMD, flags); - - // Record the domain in the hash map. - { - CrstHolder ch(&m_crstJitInfo); - m_jitInfo.AddOrReplace(entry); - } -} - -// Stack walk callback data. -struct WalkInfo -{ - StackSampler* pThis; - - // The thread in which the walk is happening and the method is executing. - // Used to obtain the app domain. - Thread* pMdThread; -}; - -// Visitor for stack walk callback. -StackWalkAction StackSampler::StackWalkCallback(CrawlFrame* pCf, VOID* data) -{ - WRAPPER_NO_CONTRACT; - - WalkInfo* info = (WalkInfo*) data; - return ((StackSampler*) info->pThis)->CrawlFrameVisitor(pCf, info->pMdThread); -} - -// Stack walk visitor helper to maintain the hash map of method desc, their count -// and the thread's domain in which the method is executing. -StackWalkAction StackSampler::CrawlFrameVisitor(CrawlFrame* pCf, Thread* pMdThread) -{ - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - MODE_ANY; - } - CONTRACTL_END; - - MethodDesc* pMD = pCf->GetFunction(); - - // Filter out methods we don't care about - if (!IsGoodMethodDesc(pMD)) - { - return SWA_CONTINUE; - } - - // Lookup the method desc and obtain info. - CountInfo info; - m_countInfo.Lookup(pMD, &info); - - // Record the current domain ID of the method's thread, i.e., - // the method is last known to be executing. - info.uCount++; - - // Put the info back. - m_countInfo.AddOrReplace(CountInfoHashEntry(pMD, info)); - - // We got the top good one, skip. - return SWA_ABORT; -} - -// Thread routine that suspends the runtime, walks the other threads' stacks to get the -// top managed method. Restarts the runtime after samples are collected. Identifies top -// methods from the samples and re-JITs them in the background. -void StackSampler::ThreadProc() -{ - CONTRACTL - { - THROWS; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - // Complete the thread init. - if (!m_pThread->HasStarted()) - { - return; - } - - // User asked us to sample after certain time. - m_pThread->UserSleep(m_nSampleAfter); - - WalkInfo info = { this, nullptr }; - - while (true) - { - EX_TRY - { - // Suspend the runtime. - ThreadSuspend::SuspendEE(ThreadSuspend::SUSPEND_OTHER); - - // Walk all other threads. - Thread* pThread = nullptr; - while ((pThread = ThreadStore::GetThreadList(pThread)) != nullptr) - { - if (pThread == m_pThread) - { - continue; - } - // TODO: Detect if thread is suspended by user before we suspended and skip. - - info.pMdThread = pThread; - - // Walk the frames. - pThread->StackWalkFrames(StackWalkCallback, &info, FUNCTIONSONLY | ALLOW_ASYNC_STACK_WALK); - } - - // Restart the runtime. - ThreadSuspend::RestartEE(FALSE, TRUE); - - // JIT the methods that frequently occur in samples. - JitFrequentMethodsInSamples(); - } - EX_CATCH - { - } - EX_END_CATCH(SwallowAllExceptions); - - // User asked us to sample every few seconds. - // TODO: Measure time to JIT using CycleTimer and subtract from the time we sleep every time. - m_pThread->UserSleep(m_nSampleEvery); - } -} - -// Find the most frequent method in the samples and JIT them. -void StackSampler::JitFrequentMethodsInSamples() -{ - struct Count - { - MethodDesc* pMD; - CountInfo info; - - static int __cdecl Decreasing(const void* e1, const void* e2) - { - return ((Count*) e2)->info.uCount - ((Count*) e1)->info.uCount; - } - }; - - // We want to keep a max-heap of the top frequent methods in the samples. - NewHolder freq(new (nothrow) Count[m_nNumMethods]); - - // - // For each element in the samples, call it incoming, add to the "frequent" list - // if the list has space to hold the incoming element. - // - // If the list doesn't have space, replace the min frequent element in the list - // with the incoming element, if the latter is more frequent. - // - unsigned uLength = 0; - for (CountInfoHash::Iterator iter = m_countInfo.Begin(), end = m_countInfo.End(); iter != end; iter++) - { - Count c = { (*iter).Key(), (*iter).Value() }; - - // Is the list full? Drop the min element if incoming is more frequent. - if (uLength == m_nNumMethods) - { - // Find the min element and the min index. - unsigned uMinIndex = 0; - unsigned uMin = freq[0].info.uCount; - for (unsigned i = 1; i < uLength; ++i) - { - if (uMin > freq[i].info.uCount) - { - uMin = freq[i].info.uCount; - uMinIndex = i; - } - } - if (uMin < c.info.uCount) - { - freq[uMinIndex] = c; - } - } - // List is not full, just add the incoming element. - else - { - freq[uLength] = c; - uLength++; - } - } - - // Sort by most frequent element first. - qsort(freq, uLength, sizeof(Count), Count::Decreasing); - -#ifdef _DEBUG - LOG((LF_JIT, LL_INFO100000, "-----------HOT METHODS-------\n")); - for (unsigned i = 0; i < uLength; ++i) - { - // printf("%s:%s, %u\n", freq[i].pMD->GetMethodTable()->GetClass()->GetDebugClassName(), freq[i].pMD->GetName(), freq[i].info.uCount); - LOG((LF_JIT, LL_INFO100000, "%s:%s, %u\n", freq[i].pMD->GetMethodTable()->GetClass()->GetDebugClassName(), freq[i].pMD->GetName(), freq[i].info.uCount)); - } - LOG((LF_JIT, LL_INFO100000, "-----------------------------\n")); -#endif - - // Do the JITting. - for (unsigned i = 0; i < uLength; ++i) - { - // If not already JITted and the method is frequent enough to be important. - if (!freq[i].info.fJitted && freq[i].info.uCount > s_knDefaultCountForImportance) - { - // Try to get the original app domain ID in which the method was JITTed, if not - // use the app domain ID the method was last seen executing. - JitAndCollectTrace(freq[i].pMD); - } - } -} - -// Invoke the JIT for the method desc. Switch to the appropriate domain. -void StackSampler::JitAndCollectTrace(MethodDesc* pMD) -{ - CONTRACTL - { - NOTHROW; - GC_TRIGGERS; - MODE_ANY; - } - CONTRACTL_END; - - // Indicate to the JIT or the JIT interface that we are JITting - // in the background for stack sampling. - CORJIT_FLAGS flags(CORJIT_FLAGS::CORJIT_FLAG_SAMPLING_JIT_BACKGROUND); - - _ASSERTE(pMD->IsIL()); - - EX_TRY - { - { - GCX_PREEMP(); - - COR_ILMETHOD_DECODER::DecoderStatus status; - NewHolder pDecoder( - new COR_ILMETHOD_DECODER(pMD->GetILHeader(), - pMD->GetMDImport(), - &status)); - -#ifdef _DEBUG - LOG((LF_JIT, LL_INFO100000, "Jitting the hot method desc using SuperPMI in the background thread -> ")); - LOG((LF_JIT, LL_INFO100000, "%s:%s\n", pMD->GetMethodTable()->GetClass()->GetDebugClassName(), pMD->GetName())); -#endif - NativeCodeVersion natCodeVer(pMD); - PrepareCodeConfigBuffer cfgBuffer(natCodeVer); - PCODE pCode = UnsafeJitFunction(cfgBuffer.GetConfig(), pDecoder, flags); - } - - // Update that this method has been already JITted. - CountInfo info; - m_countInfo.Lookup(pMD, &info); - info.fJitted = true; - m_countInfo.AddOrReplace(CountInfoHashEntry(pMD, info)); - } - EX_CATCH - { - } - EX_END_CATCH(SwallowAllExceptions) - -} - -#endif // FEATURE_STACK_SAMPLING diff --git a/src/coreclr/vm/stacksampler.h b/src/coreclr/vm/stacksampler.h deleted file mode 100644 index d489d1366ad930..00000000000000 --- a/src/coreclr/vm/stacksampler.h +++ /dev/null @@ -1,77 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/*++ - -Module Name: - - StackSampler.h - ---*/ - -#ifndef __STACK_SAMPLER_H -#define __STACK_SAMPLER_H -#endif - -#ifdef FEATURE_STACK_SAMPLING - -class StackSampler -{ -public: - // Interface - static void Init(); - static void RecordJittingInfo(MethodDesc* pMD, CORJIT_FLAGS flags); - -private: - - // Methods - StackSampler(); - ~StackSampler(); - - static DWORD __stdcall SamplingThreadProc(void* arg); - - static StackWalkAction StackWalkCallback(CrawlFrame* pCf, VOID* data); - - StackWalkAction CrawlFrameVisitor(CrawlFrame* pCf, Thread* pMdThread); - - void ThreadProc(); - - void JitFrequentMethodsInSamples(); - - void JitAndCollectTrace(MethodDesc* pMD); - - void RecordJittingInfoInternal(MethodDesc* pMD, CORJIT_FLAGS flags); - - - // Constants - static const int s_knDefaultSamplingIntervalMsec = 100; - static const int s_knDefaultNumMethods = 32; - static const int s_knDefaultCountForImportance = 0; // TODO: Set to some reasonable value. - - // Typedefs - struct CountInfo; - typedef MapSHash CountInfoHash; - typedef CountInfoHash::element_t CountInfoHashEntry; - - typedef MapSHash JitInfoHash; - typedef JitInfoHash::element_t JitInfoHashEntry; - - // Nested types - struct CountInfo - { - unsigned uCount; - bool fJitted; - CountInfo() : uCount(0), fJitted(false) {} - }; - - // Fields - Crst m_crstJitInfo; - CountInfoHash m_countInfo; - JitInfoHash m_jitInfo; - Thread* m_pThread; - unsigned m_nSampleEvery; - unsigned m_nSampleAfter; - unsigned m_nNumMethods; -}; -#endif // FEATURE_STACK_SAMPLING - diff --git a/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/ILCompilerRIDs.props b/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/ILCompilerRIDs.props index b7c6ca32c9f14e..1d51a78880ae2d 100644 --- a/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/ILCompilerRIDs.props +++ b/src/installer/pkg/projects/Microsoft.DotNet.ILCompiler/ILCompilerRIDs.props @@ -1,5 +1,7 @@ + diff --git a/src/installer/pkg/projects/netcoreappRIDs.props b/src/installer/pkg/projects/netcoreappRIDs.props index fbc6e4dc4c1a98..4c73b3dcb3c2b5 100644 --- a/src/installer/pkg/projects/netcoreappRIDs.props +++ b/src/installer/pkg/projects/netcoreappRIDs.props @@ -17,9 +17,6 @@ x86 - - arm - arm64 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 14c9aa9b4213dc..3a961b3078c9d1 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props @@ -250,6 +250,7 @@ + diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Crossgen2.sfxproj b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Crossgen2.sfxproj index c28c6ea8fb53ca..f697e4d716a56c 100644 --- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Crossgen2.sfxproj +++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Microsoft.NETCore.App.Crossgen2.sfxproj @@ -12,7 +12,7 @@ dotnet-crossgen2 crossgen2 - linux-x64;linux-musl-x64;linux-arm;linux-musl-arm;linux-arm64;linux-musl-arm64;freebsd-x64;freebsd-arm64;osx-x64;osx-arm64;win-x64;win-x86;win-arm64;win-arm + linux-x64;linux-musl-x64;linux-arm;linux-musl-arm;linux-arm64;linux-musl-arm64;freebsd-x64;freebsd-arm64;osx-x64;osx-arm64;win-x64;win-x86;win-arm64 false tools/ true @@ -85,9 +85,9 @@ $(TargetOSComponent)-$(TargetArchitecture) - + - <_Crossgen2SymbolFilesToPackage Include="@(Reference->'$(CoreCLRArtifactsPath)PDB\%(FileName).pdb')" /> + <_Crossgen2SymbolFilesToPackage Include="@(_CrossgenPublishFiles)" Condition="'%(Extension)' == '.pdb'" /> <_Crossgen2SymbolFilesToPackage Include="@(NativeRuntimeAsset->'$(CoreCLRArtifactsPdbDir)%(FileName).pdb')" Condition="'$(TargetOS)' == 'windows' and '%(FileName)' != 'crossgen2'" /> <_Crossgen2SymbolFilesToPackage Include="@(NativeRuntimeAsset->'$(CoreCLRArtifactsPath)%(FileName)%(Extension)$(SymbolsSuffix)')" Condition="'$(TargetOS)' != 'windows' and '%(FileName)' != 'crossgen2'" /> diff --git a/src/installer/tests/Assets/TestProjects/LocalizedApp/Hello.kn-IN.resx b/src/installer/tests/Assets/TestProjects/LocalizedApp/Hello.kn-IN.resx index b0ec782f9a2a68..04130790681f41 100644 --- a/src/installer/tests/Assets/TestProjects/LocalizedApp/Hello.kn-IN.resx +++ b/src/installer/tests/Assets/TestProjects/LocalizedApp/Hello.kn-IN.resx @@ -118,6 +118,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - ನಮಸ್ಕಾರ + [kn-IN] \ No newline at end of file diff --git a/src/installer/tests/Assets/TestProjects/LocalizedApp/Hello.resx b/src/installer/tests/Assets/TestProjects/LocalizedApp/Hello.resx index 81893ab57f0af6..0fad9b04a4938f 100644 --- a/src/installer/tests/Assets/TestProjects/LocalizedApp/Hello.resx +++ b/src/installer/tests/Assets/TestProjects/LocalizedApp/Hello.resx @@ -118,6 +118,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - Hello + [default] \ No newline at end of file diff --git a/src/installer/tests/Assets/TestProjects/LocalizedApp/Hello.ta-IN.resx b/src/installer/tests/Assets/TestProjects/LocalizedApp/Hello.ta-IN.resx index b42699bbee2136..4acc307a1b73db 100644 --- a/src/installer/tests/Assets/TestProjects/LocalizedApp/Hello.ta-IN.resx +++ b/src/installer/tests/Assets/TestProjects/LocalizedApp/Hello.ta-IN.resx @@ -118,6 +118,6 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - வணக்கம் + [ta-IN] \ No newline at end of file diff --git a/src/installer/tests/Assets/TestUtils/TestProjects.targets b/src/installer/tests/Assets/TestUtils/TestProjects.targets index 3aaec8fbd355aa..bb5740e9b240ec 100644 --- a/src/installer/tests/Assets/TestUtils/TestProjects.targets +++ b/src/installer/tests/Assets/TestUtils/TestProjects.targets @@ -15,7 +15,7 @@ LatestRuntimeFrameworkVersion="7.0.0" RuntimeFrameworkName="Microsoft.NETCore.App" RuntimePackNamePatterns="Microsoft.NETCore.App.Runtime.**RID**" - RuntimePackRuntimeIdentifiers="linux-arm;linux-arm64;linux-musl-arm64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;tizen.4.0.0-armel;tizen.5.0.0-armel;win-arm;win-arm64;win-x64;win-x86;linux-musl-arm;osx-arm64;maccatalyst-x64;maccatalyst-arm64;linux-s390x;linux-bionic-arm;linux-bionic-arm64;linux-bionic-x64;linux-bionic-x86" + RuntimePackRuntimeIdentifiers="linux-arm;linux-arm64;linux-musl-arm64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;tizen.4.0.0-armel;tizen.5.0.0-armel;win-arm64;win-x64;win-x86;linux-musl-arm;osx-arm64;maccatalyst-x64;maccatalyst-arm64;linux-s390x;linux-bionic-arm;linux-bionic-arm64;linux-bionic-x64;linux-bionic-x86" TargetFramework="$(NetCoreAppCurrent)" TargetingPackName="Microsoft.NETCore.App.Ref" TargetingPackVersion="7.0.0" @@ -25,7 +25,7 @@ ExcludedRuntimeIdentifiers="android" AppHostPackNamePattern="Microsoft.NETCore.App.Host.**RID**" AppHostPackVersion="7.0.0" - AppHostRuntimeIdentifiers="linux-arm;linux-arm64;linux-musl-arm64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;tizen.4.0.0-armel;tizen.5.0.0-armel;win-arm;win-arm64;win-x64;win-x86;linux-musl-arm;osx-arm64;linux-s390x;linux-bionic-arm;linux-bionic-arm64;linux-bionic-x64;linux-bionic-x86" + AppHostRuntimeIdentifiers="linux-arm;linux-arm64;linux-musl-arm64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;tizen.4.0.0-armel;tizen.5.0.0-armel;win-arm64;win-x64;win-x86;linux-musl-arm;osx-arm64;linux-s390x;linux-bionic-arm;linux-bionic-arm64;linux-bionic-x64;linux-bionic-x86" TargetFramework="$(NetCoreAppCurrent)" Condition="'@(KnownAppHostPack)' == '' or !@(KnownAppHostPack->AnyHaveMetadataValue('TargetFramework', '$(NetCoreAppCurrent)'))" /> diff --git a/src/installer/tests/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundleLocalizedApp.cs b/src/installer/tests/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundleLocalizedApp.cs index 633dd4f266d402..13a1ad7e8aec1e 100644 --- a/src/installer/tests/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundleLocalizedApp.cs +++ b/src/installer/tests/Microsoft.NET.HostModel.Tests/AppHost.Bundle.Tests/BundleLocalizedApp.cs @@ -26,20 +26,12 @@ public void Bundled_Localized_App_Run_Succeeds() var fixture = sharedTestState.TestFixture.Copy(); var singleFile = BundleSelfContainedApp(fixture); - if (OperatingSystem.IsWindows()) - { - // Set code page to output unicode characters. - Command.Create("chcp 65001").Execute(); - } - Command.Create(singleFile) .CaptureStdErr() .CaptureStdOut() .Execute() - .Should() - .Pass() - .And - .HaveStdOutContaining("\u0CA8\u0CAE\u0CB8\u0CCD\u0C95\u0CBE\u0CB0! \u0BB5\u0BA3\u0B95\u0BCD\u0B95\u0BAE\u0BCD! Hello!"); + .Should().Pass() + .And.HaveStdOutContaining("[kn-IN]! [ta-IN]! [default]!"); } public class SharedTestState : SharedTestStateBase, IDisposable diff --git a/src/installer/tests/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.AppHost.Tests/AppHostUsedWithSymbolicLinks.cs b/src/installer/tests/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.AppHost.Tests/AppHostUsedWithSymbolicLinks.cs index 3b945dae016c89..53a4b3a1c94f19 100644 --- a/src/installer/tests/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.AppHost.Tests/AppHostUsedWithSymbolicLinks.cs +++ b/src/installer/tests/Microsoft.NET.HostModel.Tests/Microsoft.NET.HostModel.AppHost.Tests/AppHostUsedWithSymbolicLinks.cs @@ -192,7 +192,6 @@ public void Put_app_directory_behind_symlink_and_use_dotnet() } [Fact] - // If enabled, this tests will need to set the console code page to output unicode characters: Command.Create("chcp 65001").Execute(); [SkipOnPlatform(TestPlatforms.Windows, "Creating symbolic links requires administrative privilege on Windows, so skip test.")] public void Put_satellite_assembly_behind_symlink() { @@ -219,7 +218,7 @@ public void Put_satellite_assembly_behind_symlink() .CaptureStdOut() .Execute() .Should().Pass() - .And.HaveStdOutContaining("\u0CA8\u0CAE\u0CB8\u0CCD\u0C95\u0CBE\u0CB0! \u0BB5\u0BA3\u0B95\u0BCD\u0B95\u0BAE\u0BCD! Hello!"); + .And.HaveStdOutContaining("[kn-IN]! [ta-IN]! [default]!"); } public class SharedTestState : IDisposable diff --git a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Evp.DigestAlgs.cs b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Evp.DigestAlgs.cs index 8ba0658735a297..d7325ca8e8574c 100644 --- a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Evp.DigestAlgs.cs +++ b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Evp.DigestAlgs.cs @@ -47,12 +47,33 @@ internal static IntPtr EvpSha512() => internal static IntPtr HashAlgorithmToEvp(string hashAlgorithmId) => hashAlgorithmId switch { - nameof(HashAlgorithmName.SHA1) => EvpSha1(), - nameof(HashAlgorithmName.SHA256) => EvpSha256(), - nameof(HashAlgorithmName.SHA384) => EvpSha384(), - nameof(HashAlgorithmName.SHA512) => EvpSha512(), - nameof(HashAlgorithmName.MD5) => EvpMd5(), + HashAlgorithmNames.SHA1 => EvpSha1(), + HashAlgorithmNames.SHA256 => EvpSha256(), + HashAlgorithmNames.SHA384 => EvpSha384(), + HashAlgorithmNames.SHA512 => EvpSha512(), + HashAlgorithmNames.MD5 => EvpMd5(), + HashAlgorithmNames.SHA3_256 or HashAlgorithmNames.SHA3_384 or HashAlgorithmNames.SHA3_512 => + throw new PlatformNotSupportedException(), _ => throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmId)) }; + + internal static bool HashAlgorithmSupported(string hashAlgorithmId) + { + switch (hashAlgorithmId) + { + case HashAlgorithmNames.SHA1: + case HashAlgorithmNames.SHA256: + case HashAlgorithmNames.SHA384: + case HashAlgorithmNames.SHA512: + case HashAlgorithmNames.MD5: + return true; + case HashAlgorithmNames.SHA3_256: + case HashAlgorithmNames.SHA3_384: + case HashAlgorithmNames.SHA3_512: + return false; + default: + throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmId)); + } + } } } diff --git a/src/libraries/Common/src/Interop/Browser/Interop.Normalization.cs b/src/libraries/Common/src/Interop/Browser/Interop.Normalization.cs deleted file mode 100644 index b55cf5307d704f..00000000000000 --- a/src/libraries/Common/src/Interop/Browser/Interop.Normalization.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. - -using System.Runtime.CompilerServices; -using System.Text; - -internal static partial class Interop -{ - internal static unsafe partial class JsGlobalization - { - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe int IsNormalized(NormalizationForm normalizationForm, in string source, out int exceptionalResult, out object result); - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe int NormalizeString(NormalizationForm normalizationForm, in string source, char* dstBuffer, int dstBufferCapacity, out int exceptionalResult, out object result); - } -} diff --git a/src/libraries/Common/src/Interop/Interop.Utils.cs b/src/libraries/Common/src/Interop/Interop.Utils.cs index b7cd0665c96483..498236c4ac4608 100644 --- a/src/libraries/Common/src/Interop/Interop.Utils.cs +++ b/src/libraries/Common/src/Interop/Interop.Utils.cs @@ -12,7 +12,7 @@ internal static partial class Interop /// increasing buffer until the size is big enough. /// internal static bool CallStringMethod( - SpanFunc interopCall, + SpanFunc interopCall, TArg1 arg1, TArg2 arg2, TArg3 arg3, out string? result) { @@ -20,19 +20,19 @@ internal static bool CallStringMethod( const int MaxHeapSize = 1280; // max from previous version of the code, starting at 80 and doubling four times Span buffer = stackalloc char[InitialSize]; - Interop.Globalization.ResultCode resultCode = interopCall(buffer, arg1, arg2, arg3); + Globalization.ResultCode resultCode = interopCall(buffer, arg1, arg2, arg3); - if (resultCode == Interop.Globalization.ResultCode.Success) + if (resultCode == Globalization.ResultCode.Success) { result = buffer.Slice(0, buffer.IndexOf('\0')).ToString(); return true; } - if (resultCode == Interop.Globalization.ResultCode.InsufficientBuffer) + if (resultCode == Globalization.ResultCode.InsufficientBuffer) { // Increase the string size and try again buffer = new char[MaxHeapSize]; - if (interopCall(buffer, arg1, arg2, arg3) == Interop.Globalization.ResultCode.Success) + if (interopCall(buffer, arg1, arg2, arg3) == Globalization.ResultCode.Success) { result = buffer.Slice(0, buffer.IndexOf('\0')).ToString(); return true; diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.DigestAlgs.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.DigestAlgs.cs index abaefab1dab6fc..dec9bdd84a5ddf 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.DigestAlgs.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EVP.DigestAlgs.cs @@ -14,45 +14,128 @@ internal static partial class Crypto private static volatile IntPtr s_evpSha256; private static volatile IntPtr s_evpSha384; private static volatile IntPtr s_evpSha512; + private static volatile IntPtr s_evpSha3_256; + private static volatile IntPtr s_evpSha3_384; + private static volatile IntPtr s_evpSha3_512; + private static volatile bool s_evpSha3_256Cached; + private static volatile bool s_evpSha3_384Cached; + private static volatile bool s_evpSha3_512Cached; [LibraryImport(Libraries.CryptoNative)] private static partial IntPtr CryptoNative_EvpMd5(); - internal static IntPtr EvpMd5() => + private static IntPtr EvpMd5() => s_evpMd5 != IntPtr.Zero ? s_evpMd5 : (s_evpMd5 = CryptoNative_EvpMd5()); [LibraryImport(Libraries.CryptoNative)] - internal static partial IntPtr CryptoNative_EvpSha1(); + private static partial IntPtr CryptoNative_EvpSha1(); - internal static IntPtr EvpSha1() => + private static IntPtr EvpSha1() => s_evpSha1 != IntPtr.Zero ? s_evpSha1 : (s_evpSha1 = CryptoNative_EvpSha1()); [LibraryImport(Libraries.CryptoNative)] - internal static partial IntPtr CryptoNative_EvpSha256(); + private static partial IntPtr CryptoNative_EvpSha256(); - internal static IntPtr EvpSha256() => + private static IntPtr EvpSha256() => s_evpSha256 != IntPtr.Zero ? s_evpSha256 : (s_evpSha256 = CryptoNative_EvpSha256()); [LibraryImport(Libraries.CryptoNative)] - internal static partial IntPtr CryptoNative_EvpSha384(); + private static partial IntPtr CryptoNative_EvpSha384(); - internal static IntPtr EvpSha384() => + private static IntPtr EvpSha384() => s_evpSha384 != IntPtr.Zero ? s_evpSha384 : (s_evpSha384 = CryptoNative_EvpSha384()); [LibraryImport(Libraries.CryptoNative)] - internal static partial IntPtr CryptoNative_EvpSha512(); + private static partial IntPtr CryptoNative_EvpSha512(); - internal static IntPtr EvpSha512() => + private static IntPtr EvpSha512() => s_evpSha512 != IntPtr.Zero ? s_evpSha512 : (s_evpSha512 = CryptoNative_EvpSha512()); - internal static IntPtr HashAlgorithmToEvp(string hashAlgorithmId) => hashAlgorithmId switch + [LibraryImport(Libraries.CryptoNative)] + private static partial IntPtr CryptoNative_EvpSha3_256(); + + private static IntPtr EvpSha3_256() + { + if (!s_evpSha3_256Cached) + { + s_evpSha3_256 = CryptoNative_EvpSha3_256(); + s_evpSha3_256Cached = true; + } + + return s_evpSha3_256; + } + + [LibraryImport(Libraries.CryptoNative)] + private static partial IntPtr CryptoNative_EvpSha3_384(); + + private static IntPtr EvpSha3_384() + { + if (!s_evpSha3_384Cached) + { + s_evpSha3_384 = CryptoNative_EvpSha3_384(); + s_evpSha3_384Cached = true; + } + + return s_evpSha3_384; + } + + [LibraryImport(Libraries.CryptoNative)] + private static partial IntPtr CryptoNative_EvpSha3_512(); + + private static IntPtr EvpSha3_512() + { + if (!s_evpSha3_512Cached) + { + s_evpSha3_512 = CryptoNative_EvpSha3_512(); + s_evpSha3_512Cached = true; + } + + return s_evpSha3_512; + } + + + internal static IntPtr HashAlgorithmToEvp(string hashAlgorithmId) + { + switch (hashAlgorithmId) + { + case HashAlgorithmNames.SHA1: return EvpSha1(); + case HashAlgorithmNames.SHA256: return EvpSha256(); + case HashAlgorithmNames.SHA384: return EvpSha384(); + case HashAlgorithmNames.SHA512: return EvpSha512(); + case HashAlgorithmNames.SHA3_256: + IntPtr sha3_256 = EvpSha3_256(); + return sha3_256 != 0 ? sha3_256 : throw new PlatformNotSupportedException(); + case HashAlgorithmNames.SHA3_384: + IntPtr sha3_384 = EvpSha3_384(); + return sha3_384 != 0 ? sha3_384 : throw new PlatformNotSupportedException(); + case HashAlgorithmNames.SHA3_512: + IntPtr sha3_512 = EvpSha3_512(); + return sha3_512 != 0 ? sha3_512 : throw new PlatformNotSupportedException(); + case nameof(HashAlgorithmName.MD5): return EvpMd5(); + default: + throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmId)); + }; + } + + internal static bool HashAlgorithmSupported(string hashAlgorithmId) { - nameof(HashAlgorithmName.SHA1) => EvpSha1(), - nameof(HashAlgorithmName.SHA256) => EvpSha256(), - nameof(HashAlgorithmName.SHA384) => EvpSha384(), - nameof(HashAlgorithmName.SHA512) => EvpSha512(), - nameof(HashAlgorithmName.MD5) => EvpMd5(), - _ => throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmId)) - }; + switch (hashAlgorithmId) + { + case HashAlgorithmNames.SHA1: + case HashAlgorithmNames.SHA256: + case HashAlgorithmNames.SHA384: + case HashAlgorithmNames.SHA512: + case HashAlgorithmNames.MD5: + return true; + case HashAlgorithmNames.SHA3_256: + return EvpSha3_256() != 0; + case HashAlgorithmNames.SHA3_384: + return EvpSha3_384() != 0; + case HashAlgorithmNames.SHA3_512: + return EvpSha3_512() != 0; + default: + throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmId)); + } + } } } 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 14a6066eeb3b75..9cc01436b9138c 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 @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; +using System.Globalization; using System.IO; using System.Net; using System.Net.Security; @@ -84,16 +85,11 @@ private static bool DisableTlsResume private static int GetCacheSize() { - int cacheSize = -1; string? value = AppContext.GetData(TlsCacheSizeCtxName) as string ?? Environment.GetEnvironmentVariable(TlsCacheSizeEnvironmentVariable); - try + if (!int.TryParse(value, CultureInfo.InvariantCulture, out int cacheSize)) { - if (value != null) - { - cacheSize = int.Parse(value); - } + cacheSize = -1; } - catch { }; return cacheSize; } diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.EventTraceGuidsEx.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.EventTraceGuidsEx.cs index 483cfe04b23238..f7d82befca494a 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.EventTraceGuidsEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.EventTraceGuidsEx.cs @@ -45,7 +45,7 @@ internal struct TRACE_ENABLE_INFO public long MatchAllKeyword; } - [LibraryImport(Interop.Libraries.Advapi32)] + [LibraryImport(Libraries.Advapi32)] internal static unsafe partial int EnumerateTraceGuidsEx( TRACE_QUERY_INFO_CLASS TraceQueryInfoClass, void* InBuffer, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.EventWriteTransfer.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.EventWriteTransfer.cs index d66fe12d87a9bd..1c1438adb1d020 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.EventWriteTransfer.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.EventWriteTransfer.cs @@ -32,7 +32,7 @@ internal static unsafe int EventWriteTransfer( return HResult; } - [LibraryImport(Interop.Libraries.Advapi32, EntryPoint = "EventWriteTransfer")] + [LibraryImport(Libraries.Advapi32, EntryPoint = "EventWriteTransfer")] private static unsafe partial int EventWriteTransfer_PInvoke( long registrationHandle, in EventDescriptor eventDescriptor, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetTokenInformation_void.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetTokenInformation_void.cs index e61ce35a91f97a..02f7b03c5812ef 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetTokenInformation_void.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.GetTokenInformation_void.cs @@ -9,7 +9,7 @@ internal static partial class Interop { internal static partial class Advapi32 { - [LibraryImport(Interop.Libraries.Advapi32, SetLastError = true)] + [LibraryImport(Libraries.Advapi32, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static unsafe partial bool GetTokenInformation( SafeTokenHandle TokenHandle, diff --git a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegCreateKeyEx.cs b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegCreateKeyEx.cs index 9e5e420146e191..e7cde43076f554 100644 --- a/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegCreateKeyEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Advapi32/Interop.RegCreateKeyEx.cs @@ -22,7 +22,7 @@ internal static partial int RegCreateKeyEx( string? lpClass, int dwOptions, int samDesired, - ref Interop.Kernel32.SECURITY_ATTRIBUTES secAttrs, + ref Kernel32.SECURITY_ATTRIBUTES secAttrs, out SafeRegistryHandle hkResult, out int lpdwDisposition); } diff --git a/src/libraries/Common/src/Interop/Windows/BCrypt/BCryptAlgorithmCache.cs b/src/libraries/Common/src/Interop/Windows/BCrypt/BCryptAlgorithmCache.cs index aec34aeb523478..5f060292a666c7 100644 --- a/src/libraries/Common/src/Interop/Windows/BCrypt/BCryptAlgorithmCache.cs +++ b/src/libraries/Common/src/Interop/Windows/BCrypt/BCryptAlgorithmCache.cs @@ -13,6 +13,7 @@ internal static partial class BCrypt internal static class BCryptAlgorithmCache { private static readonly ConcurrentDictionary<(string HashAlgorithmId, BCryptOpenAlgorithmProviderFlags Flags), (SafeBCryptAlgorithmHandle Handle, int HashSizeInBytes)> s_handles = new(); + private static readonly ConcurrentDictionary<(string HashAlgorithmId, BCryptOpenAlgorithmProviderFlags Flags), bool> s_supported = new(); /// /// Returns a SafeBCryptAlgorithmHandle of the desired algorithm and flags. This is a shared handle so do not dispose it! @@ -43,6 +44,42 @@ public static unsafe SafeBCryptAlgorithmHandle GetCachedBCryptAlgorithmHandle(st } } } + + public static unsafe bool IsBCryptAlgorithmSupported(string hashAlgorithmId, BCryptOpenAlgorithmProviderFlags flags) + { + var key = (hashAlgorithmId, flags); + + if (s_supported.TryGetValue(key, out bool supported)) + { + return supported; + } + + NTSTATUS status = BCryptOpenAlgorithmProvider( + out SafeBCryptAlgorithmHandle handle, + key.hashAlgorithmId, + null, + key.flags); + + bool isSupported = status == NTSTATUS.STATUS_SUCCESS; + + if (s_supported.TryAdd(key, isSupported) && isSupported) + { + // It's a valid algorithm. Let's prime the handle cache while we are here. Presumably it's + // going to get used if we're asking if it's supported. + int hashSize = BCryptGetDWordProperty(handle, BCryptPropertyStrings.BCRYPT_HASH_LENGTH); + Debug.Assert(hashSize > 0); + + if (s_handles.TryAdd(key, (handle, hashSize))) + { + // If we added the handle to the cache, don't dispose of it and return our answer. + return isSupported; + } + } + + // Either the algorithm isn't supported or we don't need it for priming the cache, so Dispose. + handle.Dispose(); + return isSupported; + } } } } diff --git a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptAlgPseudoHandle.cs b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptAlgPseudoHandle.cs index 57c508bf709479..d0a4e878f2764a 100644 --- a/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptAlgPseudoHandle.cs +++ b/src/libraries/Common/src/Interop/Windows/BCrypt/Interop.BCryptAlgPseudoHandle.cs @@ -23,6 +23,12 @@ public enum BCryptAlgPseudoHandle : uint BCRYPT_HMAC_SHA384_ALG_HANDLE = 0x000000c1, BCRYPT_HMAC_SHA512_ALG_HANDLE = 0x000000d1, BCRYPT_PBKDF2_ALG_HANDLE = 0x00000331, + BCRYPT_SHA3_256_ALG_HANDLE = 0x000003B1, + BCRYPT_SHA3_384_ALG_HANDLE = 0x000003C1, + BCRYPT_SHA3_512_ALG_HANDLE = 0x000003D1, + BCRYPT_HMAC_SHA3_256_ALG_HANDLE = 0x000003E1, + BCRYPT_HMAC_SHA3_384_ALG_HANDLE = 0x000003F1, + BCRYPT_HMAC_SHA3_512_ALG_HANDLE = 0x00000401, } internal static bool PseudoHandlesSupported { get; } = diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CopyFile.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CopyFile.cs index 001c7afc08a5ea..8fd8476677f482 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CopyFile.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.CopyFile.cs @@ -10,14 +10,14 @@ internal static partial class Kernel32 { internal static int CopyFile(string src, string dst, bool failIfExists) { - int copyFlags = failIfExists ? Interop.Kernel32.FileOperations.COPY_FILE_FAIL_IF_EXISTS : 0; + int copyFlags = failIfExists ? FileOperations.COPY_FILE_FAIL_IF_EXISTS : 0; int cancel = 0; - if (!Interop.Kernel32.CopyFileEx(src, dst, IntPtr.Zero, IntPtr.Zero, ref cancel, copyFlags)) + if (!CopyFileEx(src, dst, IntPtr.Zero, IntPtr.Zero, ref cancel, copyFlags)) { return Marshal.GetLastPInvokeError(); } - return Interop.Errors.ERROR_SUCCESS; + return Errors.ERROR_SUCCESS; } } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FileTimeToSystemTime.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FileTimeToSystemTime.cs index 0eac8ca5cff91f..c00eb8655478d8 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FileTimeToSystemTime.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.FileTimeToSystemTime.cs @@ -9,6 +9,6 @@ internal static partial class Kernel32 { [LibraryImport(Libraries.Kernel32)] [SuppressGCTransition] - internal static unsafe partial Interop.BOOL FileTimeToSystemTime(ulong* lpFileTime, Interop.Kernel32.SYSTEMTIME* lpSystemTime); + internal static unsafe partial BOOL FileTimeToSystemTime(ulong* lpFileTime, SYSTEMTIME* lpSystemTime); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetCPInfo.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetCPInfo.cs index 7f4558d05ac7f1..ad9aa0da87ccba 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetCPInfo.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetCPInfo.cs @@ -17,6 +17,6 @@ internal unsafe struct CPINFO } [LibraryImport(Libraries.Kernel32)] - internal static unsafe partial Interop.BOOL GetCPInfo(uint codePage, CPINFO* lpCpInfo); + internal static unsafe partial BOOL GetCPInfo(uint codePage, CPINFO* lpCpInfo); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetCurrentProcessorNumberEx.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetCurrentProcessorNumberEx.cs index 4ca0d0eeb4f8f5..1224f926efc21a 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetCurrentProcessorNumberEx.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetCurrentProcessorNumberEx.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [StructLayoutAttribute(LayoutKind.Sequential)] + [StructLayout(LayoutKind.Sequential)] internal struct PROCESSOR_NUMBER { public ushort Group; diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetSystemTime.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetSystemTime.cs index 9b80349ca1b609..a276d59314aa02 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetSystemTime.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.GetSystemTime.cs @@ -9,6 +9,6 @@ internal static partial class Kernel32 { [LibraryImport(Libraries.Kernel32)] [SuppressGCTransition] - internal static unsafe partial void GetSystemTime(Interop.Kernel32.SYSTEMTIME* lpSystemTime); + internal static unsafe partial void GetSystemTime(SYSTEMTIME* lpSystemTime); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Globalization.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Globalization.cs index 99e18caf50b1c4..ca34cca3a34599 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Globalization.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.Globalization.cs @@ -117,7 +117,7 @@ internal static unsafe partial bool IsNLSDefinedString( int cchStr); [LibraryImport("kernel32.dll")] - internal static unsafe partial Interop.BOOL GetUserPreferredUILanguages(uint dwFlags, uint* pulNumLanguages, char* pwszLanguagesBuffer, uint* pcchLanguagesBuffer); + internal static unsafe partial BOOL GetUserPreferredUILanguages(uint dwFlags, uint* pulNumLanguages, char* pwszLanguagesBuffer, uint* pcchLanguagesBuffer); [LibraryImport("kernel32.dll", StringMarshalling = StringMarshalling.Utf16)] internal static unsafe partial int GetLocaleInfoEx(string lpLocaleName, uint LCType, void* lpLCData, int cchData); diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.OutputDebugString.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.OutputDebugString.cs index 0012b5de2899d7..684a575ecb9085 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.OutputDebugString.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.OutputDebugString.cs @@ -7,7 +7,7 @@ internal static partial class Interop { internal static partial class Kernel32 { - [LibraryImport(Interop.Libraries.Kernel32, EntryPoint = "OutputDebugStringW", StringMarshalling = StringMarshalling.Utf16)] + [LibraryImport(Libraries.Kernel32, EntryPoint = "OutputDebugStringW", StringMarshalling = StringMarshalling.Utf16)] internal static partial void OutputDebugString(string message); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SystemTimeToFileTime.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SystemTimeToFileTime.cs index 9b267a480126c2..2cb594e3cdf9ad 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SystemTimeToFileTime.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.SystemTimeToFileTime.cs @@ -9,6 +9,6 @@ internal static partial class Kernel32 { [LibraryImport(Libraries.Kernel32)] [SuppressGCTransition] - internal static unsafe partial Interop.BOOL SystemTimeToFileTime(Interop.Kernel32.SYSTEMTIME* lpSystemTime, ulong* lpFileTime); + internal static unsafe partial BOOL SystemTimeToFileTime(SYSTEMTIME* lpSystemTime, ulong* lpFileTime); } } diff --git a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.TzSpecificLocalTimeToSystemTime.cs b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.TzSpecificLocalTimeToSystemTime.cs index de38b9e0a96c42..b38ffdb2efe50c 100644 --- a/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.TzSpecificLocalTimeToSystemTime.cs +++ b/src/libraries/Common/src/Interop/Windows/Kernel32/Interop.TzSpecificLocalTimeToSystemTime.cs @@ -9,9 +9,9 @@ internal static partial class Interop internal static partial class Kernel32 { [LibraryImport(Libraries.Kernel32)] - internal static unsafe partial Interop.BOOL TzSpecificLocalTimeToSystemTime( + internal static unsafe partial BOOL TzSpecificLocalTimeToSystemTime( IntPtr lpTimeZoneInformation, - Interop.Kernel32.SYSTEMTIME* lpLocalTime, - Interop.Kernel32.SYSTEMTIME* lpUniversalTime); + SYSTEMTIME* lpLocalTime, + SYSTEMTIME* lpUniversalTime); } } diff --git a/src/libraries/Common/src/Interop/Windows/NtDll/Interop.NtCreateFile.cs b/src/libraries/Common/src/Interop/Windows/NtDll/Interop.NtCreateFile.cs index cc80f325702c3c..d1a07c14221ef9 100644 --- a/src/libraries/Common/src/Interop/Windows/NtDll/Interop.NtCreateFile.cs +++ b/src/libraries/Common/src/Interop/Windows/NtDll/Interop.NtCreateFile.cs @@ -203,7 +203,7 @@ public enum CreateDisposition : uint /// /// Open if exists or fail if doesn't exist. Equivalent to OPEN_EXISTING or - /// . + /// . /// /// /// TruncateExisting also uses Open and then manually truncates the file @@ -214,25 +214,25 @@ public enum CreateDisposition : uint /// /// Create if doesn't exist or fail if does exist. Equivalent to CREATE_NEW - /// or . + /// or . /// FILE_CREATE = 2, /// /// Open if exists or create if doesn't exist. Equivalent to OPEN_ALWAYS or - /// . + /// . /// FILE_OPEN_IF = 3, /// /// Open and overwrite if exists or fail if doesn't exist. Equivalent to - /// TRUNCATE_EXISTING or . + /// TRUNCATE_EXISTING or . /// FILE_OVERWRITE = 4, /// /// Open and overwrite if exists or create if doesn't exist. Equivalent to - /// CREATE_ALWAYS or . + /// CREATE_ALWAYS or . /// FILE_OVERWRITE_IF = 5 } diff --git a/src/libraries/Common/src/Interop/Windows/Ole32/Interop.CLSIDFromProgID.cs b/src/libraries/Common/src/Interop/Windows/Ole32/Interop.CLSIDFromProgID.cs index 5a9b58d6bd72de..cf2108ec6ab020 100644 --- a/src/libraries/Common/src/Interop/Windows/Ole32/Interop.CLSIDFromProgID.cs +++ b/src/libraries/Common/src/Interop/Windows/Ole32/Interop.CLSIDFromProgID.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Ole32 { - [LibraryImport(Interop.Libraries.Ole32, StringMarshalling = StringMarshalling.Utf16)] + [LibraryImport(Libraries.Ole32, StringMarshalling = StringMarshalling.Utf16)] internal static partial int CLSIDFromProgID(string lpszProgID, out Guid lpclsid); } } diff --git a/src/libraries/Common/src/Interop/Windows/Ole32/Interop.CoCreateGuid.cs b/src/libraries/Common/src/Interop/Windows/Ole32/Interop.CoCreateGuid.cs index 92b36a053dd533..ad8e77784cf8b2 100644 --- a/src/libraries/Common/src/Interop/Windows/Ole32/Interop.CoCreateGuid.cs +++ b/src/libraries/Common/src/Interop/Windows/Ole32/Interop.CoCreateGuid.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Ole32 { - [LibraryImport(Interop.Libraries.Ole32)] + [LibraryImport(Libraries.Ole32)] internal static partial int CoCreateGuid(out Guid guid); } } diff --git a/src/libraries/Common/src/Interop/Windows/Ole32/Interop.CoGetStandardMarshal.cs b/src/libraries/Common/src/Interop/Windows/Ole32/Interop.CoGetStandardMarshal.cs index 11d26766d5063c..299c598e061671 100644 --- a/src/libraries/Common/src/Interop/Windows/Ole32/Interop.CoGetStandardMarshal.cs +++ b/src/libraries/Common/src/Interop/Windows/Ole32/Interop.CoGetStandardMarshal.cs @@ -8,7 +8,7 @@ internal static partial class Interop { internal static partial class Ole32 { - [LibraryImport(Interop.Libraries.Ole32)] + [LibraryImport(Libraries.Ole32)] internal static partial int CoGetStandardMarshal(ref Guid riid, IntPtr pv, int dwDestContext, IntPtr pvDestContext, int mshlflags, out IntPtr ppMarshal); } } diff --git a/src/libraries/Common/src/System/Collections/Concurrent/MultiProducerMultiConsumerQueue.cs b/src/libraries/Common/src/System/Collections/Concurrent/MultiProducerMultiConsumerQueue.cs index e9da29081a3180..4fac49a6dfb25f 100644 --- a/src/libraries/Common/src/System/Collections/Concurrent/MultiProducerMultiConsumerQueue.cs +++ b/src/libraries/Common/src/System/Collections/Concurrent/MultiProducerMultiConsumerQueue.cs @@ -15,21 +15,21 @@ internal sealed class MultiProducerMultiConsumerQueue : ConcurrentQueue, I { /// Enqueues an item into the queue. /// The item to enqueue. - void IProducerConsumerQueue.Enqueue(T item) { base.Enqueue(item); } + void IProducerConsumerQueue.Enqueue(T item) { Enqueue(item); } /// Attempts to dequeue an item from the queue. /// The dequeued item. /// true if an item could be dequeued; otherwise, false. - bool IProducerConsumerQueue.TryDequeue([MaybeNullWhen(false)] out T result) { return base.TryDequeue(out result); } + bool IProducerConsumerQueue.TryDequeue([MaybeNullWhen(false)] out T result) { return TryDequeue(out result); } /// Gets whether the collection is currently empty. - bool IProducerConsumerQueue.IsEmpty => base.IsEmpty; + bool IProducerConsumerQueue.IsEmpty => IsEmpty; /// Gets the number of items in the collection. - int IProducerConsumerQueue.Count => base.Count; + int IProducerConsumerQueue.Count => Count; /// A thread-safe way to get the number of items in the collection. May synchronize access by locking the provided synchronization object. /// ConcurrentQueue.Count is thread safe, no need to acquire the lock. - int IProducerConsumerQueue.GetCountSafe(object syncObj) => base.Count; + int IProducerConsumerQueue.GetCountSafe(object syncObj) => Count; } } diff --git a/src/libraries/Common/src/System/Diagnostics/DiagnosticsHelper.cs b/src/libraries/Common/src/System/Diagnostics/DiagnosticsHelper.cs index 18f10c0d520d87..ce7f345b0ea9cd 100644 --- a/src/libraries/Common/src/System/Diagnostics/DiagnosticsHelper.cs +++ b/src/libraries/Common/src/System/Diagnostics/DiagnosticsHelper.cs @@ -32,7 +32,7 @@ internal static bool CompareTags(List>? sortedTags } int count = sortedTags.Count; - int size = count / (sizeof(long) * 8) + 1; + int size = count / (sizeof(ulong) * 8) + 1; BitMapper bitMapper = new BitMapper(size <= 100 ? stackalloc ulong[size] : new ulong[size]); if (tags2 is ICollection> tagsCol) @@ -124,15 +124,15 @@ public BitMapper(Span bitMap) { _bitMap = bitMap; _bitMap.Clear(); - _maxIndex = bitMap.Length * sizeof(long) * 8; + _maxIndex = bitMap.Length * sizeof(ulong) * 8; } public int MaxIndex => _maxIndex; private static void GetIndexAndMask(int index, out int bitIndex, out ulong mask) { - bitIndex = index >> 6; - int bit = index & (sizeof(long) * 8 - 1); + bitIndex = index >> 6; // divide by 64 == (sizeof(ulong) * 8) bits + int bit = index & (sizeof(ulong) * 8 - 1); mask = 1UL << bit; } diff --git a/src/libraries/Common/src/System/IO/PathInternal.cs b/src/libraries/Common/src/System/IO/PathInternal.cs index c6ea2e2261805e..a07d5cafffde2a 100644 --- a/src/libraries/Common/src/System/IO/PathInternal.cs +++ b/src/libraries/Common/src/System/IO/PathInternal.cs @@ -128,7 +128,7 @@ internal static bool RemoveRelativeSegments(ReadOnlySpan path, int rootLen // We treat "\.." , "\." and "\\" as a relative segment. We want to collapse the first separator past the root presuming // the root actually ends in a separator. Otherwise the first segment for RemoveRelativeSegments // in cases like "\\?\C:\.\" and "\\?\C:\..\", the first segment after the root will be ".\" and "..\" which is not considered as a relative segment and hence not be removed. - if (PathInternal.IsDirectorySeparator(path[skip - 1])) + if (IsDirectorySeparator(path[skip - 1])) skip--; // Remove "//", "/./", and "/../" from the path by copying each character to the output, @@ -143,18 +143,18 @@ internal static bool RemoveRelativeSegments(ReadOnlySpan path, int rootLen { char c = path[i]; - if (PathInternal.IsDirectorySeparator(c) && i + 1 < path.Length) + if (IsDirectorySeparator(c) && i + 1 < path.Length) { // Skip this character if it's a directory separator and if the next character is, too, // e.g. "parent//child" => "parent/child" - if (PathInternal.IsDirectorySeparator(path[i + 1])) + if (IsDirectorySeparator(path[i + 1])) { continue; } // Skip this character and the next if it's referring to the current directory, // e.g. "parent/./child" => "parent/child" - if ((i + 2 == path.Length || PathInternal.IsDirectorySeparator(path[i + 2])) && + if ((i + 2 == path.Length || IsDirectorySeparator(path[i + 2])) && path[i + 1] == '.') { i++; @@ -164,14 +164,14 @@ internal static bool RemoveRelativeSegments(ReadOnlySpan path, int rootLen // Skip this character and the next two if it's referring to the parent directory, // e.g. "parent/child/../grandchild" => "parent/grandchild" if (i + 2 < path.Length && - (i + 3 == path.Length || PathInternal.IsDirectorySeparator(path[i + 3])) && + (i + 3 == path.Length || IsDirectorySeparator(path[i + 3])) && path[i + 1] == '.' && path[i + 2] == '.') { // Unwind back to the last slash (and if there isn't one, clear out everything). int s; for (s = sb.Length - 1; s >= skip; s--) { - if (PathInternal.IsDirectorySeparator(sb[s])) + if (IsDirectorySeparator(sb[s])) { sb.Length = (i + 3 >= path.Length && s == skip) ? s + 1 : s; // to avoid removing the complete "\tmp\" segment in cases like \\?\C:\tmp\..\, C:\tmp\.. break; @@ -188,9 +188,9 @@ internal static bool RemoveRelativeSegments(ReadOnlySpan path, int rootLen } // Normalize the directory separator if needed - if (c != PathInternal.DirectorySeparatorChar && c == PathInternal.AltDirectorySeparatorChar) + if (c != DirectorySeparatorChar && c == AltDirectorySeparatorChar) { - c = PathInternal.DirectorySeparatorChar; + c = DirectorySeparatorChar; flippedSeparator = true; } diff --git a/src/libraries/Common/src/System/Net/Http/X509ResourceClient.cs b/src/libraries/Common/src/System/Net/Http/X509ResourceClient.cs index 5fe2b8ce402382..57538487800e1e 100644 --- a/src/libraries/Common/src/System/Net/Http/X509ResourceClient.cs +++ b/src/libraries/Common/src/System/Net/Http/X509ResourceClient.cs @@ -12,7 +12,7 @@ namespace System.Net.Http { internal static partial class X509ResourceClient { - private static readonly Func>? s_downloadBytes = CreateDownloadBytesFunc(); + private static readonly Func>? s_downloadBytes = CreateDownloadBytesFunc(); static partial void ReportNoClient(); static partial void ReportNegativeTimeout(); @@ -24,18 +24,17 @@ internal static partial class X509ResourceClient internal static byte[]? DownloadAsset(string uri, TimeSpan downloadTimeout) { - ValueTask task = DownloadAssetCore(uri, downloadTimeout, async: false); + Task task = DownloadAssetCore(uri, downloadTimeout, async: false); Debug.Assert(task.IsCompletedSuccessfully); return task.Result; } internal static Task DownloadAssetAsync(string uri, TimeSpan downloadTimeout) { - ValueTask task = DownloadAssetCore(uri, downloadTimeout, async: true); - return task.AsTask(); + return DownloadAssetCore(uri, downloadTimeout, async: true); } - private static async ValueTask DownloadAssetCore(string uri, TimeSpan downloadTimeout, bool async) + private static async Task DownloadAssetCore(string uri, TimeSpan downloadTimeout, bool async) { if (s_downloadBytes is null) { @@ -60,8 +59,12 @@ internal static partial class X509ResourceClient try { - ret = await s_downloadBytes(uri, cts?.Token ?? default, async).ConfigureAwait(false); - return ret; + Task task = s_downloadBytes(uri, cts?.Token ?? default, async); + await ((Task)task).ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing); + if (task.IsCompletedSuccessfully) + { + return task.Result; + } } catch { } finally @@ -74,7 +77,7 @@ internal static partial class X509ResourceClient return null; } - private static Func>? CreateDownloadBytesFunc() + private static Func>? CreateDownloadBytesFunc() { try { diff --git a/src/libraries/Common/src/System/Security/Cryptography/HashOneShotHelpers.cs b/src/libraries/Common/src/System/Security/Cryptography/HashOneShotHelpers.cs index debc16c329b1e5..f80e69c8bf53a8 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/HashOneShotHelpers.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/HashOneShotHelpers.cs @@ -12,28 +12,18 @@ internal static class HashOneShotHelpers { internal static byte[] HashData(HashAlgorithmName hashAlgorithm, ReadOnlySpan source) { - if (hashAlgorithm == HashAlgorithmName.SHA256) - { - return SHA256.HashData(source); - } - else if (hashAlgorithm == HashAlgorithmName.SHA1) - { - return SHA1.HashData(source); - } - else if (hashAlgorithm == HashAlgorithmName.SHA512) - { - return SHA512.HashData(source); - } - else if (hashAlgorithm == HashAlgorithmName.SHA384) - { - return SHA384.HashData(source); - } - else if (Helpers.HasMD5 && hashAlgorithm == HashAlgorithmName.MD5) - { - return MD5.HashData(source); - } - - throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name)); + return hashAlgorithm.Name switch + { + HashAlgorithmNames.SHA256 => SHA256.HashData(source), + HashAlgorithmNames.SHA1 => SHA1.HashData(source), + HashAlgorithmNames.SHA512 => SHA512.HashData(source), + HashAlgorithmNames.SHA384 => SHA384.HashData(source), + HashAlgorithmNames.SHA3_256 => SHA3_256.HashData(source), + HashAlgorithmNames.SHA3_384 => SHA3_384.HashData(source), + HashAlgorithmNames.SHA3_512 => SHA3_512.HashData(source), + HashAlgorithmNames.MD5 when Helpers.HasMD5 => MD5.HashData(source), + _ => throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name)), + }; } internal static bool TryHashData( @@ -42,54 +32,34 @@ internal static bool TryHashData( Span destination, out int bytesWritten) { - if (hashAlgorithm == HashAlgorithmName.SHA256) - { - return SHA256.TryHashData(source, destination, out bytesWritten); - } - else if (hashAlgorithm == HashAlgorithmName.SHA1) - { - return SHA1.TryHashData(source, destination, out bytesWritten); - } - else if (hashAlgorithm == HashAlgorithmName.SHA512) - { - return SHA512.TryHashData(source, destination, out bytesWritten); - } - else if (hashAlgorithm == HashAlgorithmName.SHA384) - { - return SHA384.TryHashData(source, destination, out bytesWritten); - } - else if (Helpers.HasMD5 && hashAlgorithm == HashAlgorithmName.MD5) - { - return MD5.TryHashData(source, destination, out bytesWritten); - } - - throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name)); + return hashAlgorithm.Name switch + { + HashAlgorithmNames.SHA256 => SHA256.TryHashData(source, destination, out bytesWritten), + HashAlgorithmNames.SHA1 => SHA1.TryHashData(source, destination, out bytesWritten), + HashAlgorithmNames.SHA512 => SHA512.TryHashData(source, destination, out bytesWritten), + HashAlgorithmNames.SHA384 => SHA384.TryHashData(source, destination, out bytesWritten), + HashAlgorithmNames.SHA3_256 => SHA3_256.TryHashData(source, destination, out bytesWritten), + HashAlgorithmNames.SHA3_384 => SHA3_384.TryHashData(source, destination, out bytesWritten), + HashAlgorithmNames.SHA3_512 => SHA3_512.TryHashData(source, destination, out bytesWritten), + HashAlgorithmNames.MD5 when Helpers.HasMD5 => MD5.TryHashData(source, destination, out bytesWritten), + _ => throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name)), + }; } internal static byte[] HashData(HashAlgorithmName hashAlgorithm, Stream source) { - if (hashAlgorithm == HashAlgorithmName.SHA256) - { - return SHA256.HashData(source); - } - else if (hashAlgorithm == HashAlgorithmName.SHA1) - { - return SHA1.HashData(source); - } - else if (hashAlgorithm == HashAlgorithmName.SHA512) - { - return SHA512.HashData(source); - } - else if (hashAlgorithm == HashAlgorithmName.SHA384) - { - return SHA384.HashData(source); - } - else if (Helpers.HasMD5 && hashAlgorithm == HashAlgorithmName.MD5) - { - return MD5.HashData(source); - } - - throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name)); + return hashAlgorithm.Name switch + { + HashAlgorithmNames.SHA256 => SHA256.HashData(source), + HashAlgorithmNames.SHA1 => SHA1.HashData(source), + HashAlgorithmNames.SHA512 => SHA512.HashData(source), + HashAlgorithmNames.SHA384 => SHA384.HashData(source), + HashAlgorithmNames.SHA3_256 => SHA3_256.HashData(source), + HashAlgorithmNames.SHA3_384 => SHA3_384.HashData(source), + HashAlgorithmNames.SHA3_512 => SHA3_512.HashData(source), + HashAlgorithmNames.MD5 when Helpers.HasMD5 => MD5.HashData(source), + _ => throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name)), + }; } internal static int MacData( @@ -98,28 +68,18 @@ internal static int MacData( ReadOnlySpan source, Span destination) { - if (hashAlgorithm == HashAlgorithmName.SHA256) - { - return HMACSHA256.HashData(key, source, destination); - } - else if (hashAlgorithm == HashAlgorithmName.SHA1) - { - return HMACSHA1.HashData(key, source, destination); - } - else if (hashAlgorithm == HashAlgorithmName.SHA512) - { - return HMACSHA512.HashData(key, source, destination); - } - else if (hashAlgorithm == HashAlgorithmName.SHA384) - { - return HMACSHA384.HashData(key, source, destination); - } - else if (Helpers.HasMD5 && hashAlgorithm == HashAlgorithmName.MD5) - { - return HMACMD5.HashData(key, source, destination); - } - - throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name)); + return hashAlgorithm.Name switch + { + HashAlgorithmNames.SHA256 => HMACSHA256.HashData(key, source, destination), + HashAlgorithmNames.SHA1 => HMACSHA1.HashData(key, source, destination), + HashAlgorithmNames.SHA512 => HMACSHA512.HashData(key, source, destination), + HashAlgorithmNames.SHA384 => HMACSHA384.HashData(key, source, destination), + HashAlgorithmNames.SHA3_256 => HMACSHA3_256.HashData(key, source, destination), + HashAlgorithmNames.SHA3_384 => HMACSHA3_384.HashData(key, source, destination), + HashAlgorithmNames.SHA3_512 => HMACSHA3_512.HashData(key, source, destination), + HashAlgorithmNames.MD5 when Helpers.HasMD5 => HMACMD5.HashData(key, source, destination), + _ => throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name)), + }; } } } diff --git a/src/libraries/Common/src/System/Security/Cryptography/Oids.cs b/src/libraries/Common/src/System/Security/Cryptography/Oids.cs index 40e761dab09d4c..b7364108222ad1 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/Oids.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/Oids.cs @@ -24,6 +24,9 @@ internal static partial class Oids internal const string RsaPkcs1Sha256 = "1.2.840.113549.1.1.11"; internal const string RsaPkcs1Sha384 = "1.2.840.113549.1.1.12"; internal const string RsaPkcs1Sha512 = "1.2.840.113549.1.1.13"; + internal const string RsaPkcs1Sha3_256 = "2.16.840.1.101.3.4.3.14"; + internal const string RsaPkcs1Sha3_384 = "2.16.840.1.101.3.4.3.15"; + internal const string RsaPkcs1Sha3_512 = "2.16.840.1.101.3.4.3.16"; internal const string Esdh = "1.2.840.113549.1.9.16.3.5"; internal const string EcDiffieHellman = "1.3.132.1.12"; internal const string DiffieHellman = "1.2.840.10046.2.1"; @@ -65,6 +68,9 @@ internal static partial class Oids internal const string Sha256 = "2.16.840.1.101.3.4.2.1"; internal const string Sha384 = "2.16.840.1.101.3.4.2.2"; internal const string Sha512 = "2.16.840.1.101.3.4.2.3"; + internal const string Sha3_256 = "2.16.840.1.101.3.4.2.8"; + internal const string Sha3_384 = "2.16.840.1.101.3.4.2.9"; + internal const string Sha3_512 = "2.16.840.1.101.3.4.2.10"; // DSA CMS uses the combined signature+digest OID internal const string DsaWithSha1 = "1.2.840.10040.4.3"; @@ -84,6 +90,10 @@ internal static partial class Oids internal const string ECDsaWithSha384 = "1.2.840.10045.4.3.3"; internal const string ECDsaWithSha512 = "1.2.840.10045.4.3.4"; + internal const string ECDsaWithSha3_256 = "2.16.840.1.101.3.4.3.10"; + internal const string ECDsaWithSha3_384 = "2.16.840.1.101.3.4.3.11"; + internal const string ECDsaWithSha3_512 = "2.16.840.1.101.3.4.3.12"; + internal const string Mgf1 = "1.2.840.113549.1.1.8"; internal const string PSpecified = "1.2.840.113549.1.1.9"; diff --git a/src/libraries/Common/src/System/Security/Cryptography/RSAOpenSsl.cs b/src/libraries/Common/src/System/Security/Cryptography/RSAOpenSsl.cs index dc002fdfd59732..34ad612323f2d7 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/RSAOpenSsl.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/RSAOpenSsl.cs @@ -873,6 +873,18 @@ private static void ValidatePadding(RSAEncryptionPadding padding) { throw PaddingModeNotSupported(); } + + // If the hash algorithm is not supported by the platform, such as SHA3, then we don't support it for + // RSAOpenSsl, even if OpenSSL itself might support OAEP-SHA3. We use the platform's hashing in some + // places for RSA, regardless of what is implementing RSA. If RSAOpenSsl were used on macOS, then + // there would be some incongruence between what hashes OpenSSL supports and what macOS support. Signing + // for example, always uses the platform's implementation of hashing. + if (padding.Mode == RSAEncryptionPaddingMode.Oaep && + padding.OaepHashAlgorithm.Name is string name && + !HashProviderDispenser.HashSupported(name)) + { + throw new PlatformNotSupportedException(); + } } private static void ValidatePadding(RSASignaturePadding padding) diff --git a/src/libraries/Common/src/System/Security/Cryptography/RsaPaddingProcessor.cs b/src/libraries/Common/src/System/Security/Cryptography/RsaPaddingProcessor.cs index 4db95b2ff4d242..66256440b7e708 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/RsaPaddingProcessor.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/RsaPaddingProcessor.cs @@ -44,41 +44,62 @@ internal static class RsaPaddingProcessor 0x40, }; + private static ReadOnlySpan DigestInfoSha3_256 => new byte[] + { + 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x08, 0x05, 0x00, 0x04, + 0x20, + }; + + private static ReadOnlySpan DigestInfoSha3_384 => new byte[] + { + 0x30, 0x41, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x09, 0x05, 0x00, 0x04, + 0x30, + }; + + private static ReadOnlySpan DigestInfoSha3_512 => new byte[] + { + 0x30, 0x51, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, + 0x01, 0x65, 0x03, 0x04, 0x02, 0x0A, 0x05, 0x00, 0x04, + 0x40, + }; + private static ReadOnlySpan EightZeros => new byte[8]; private static ReadOnlySpan GetDigestInfoForAlgorithm( HashAlgorithmName hashAlgorithmName, out int digestLengthInBytes) { - if (hashAlgorithmName == HashAlgorithmName.MD5) - { - digestLengthInBytes = MD5.HashSizeInBytes; - return DigestInfoMD5; - } - else if (hashAlgorithmName == HashAlgorithmName.SHA1) - { - digestLengthInBytes = SHA1.HashSizeInBytes; - return DigestInfoSha1; - } - else if (hashAlgorithmName == HashAlgorithmName.SHA256) - { - digestLengthInBytes = SHA256.HashSizeInBytes; - return DigestInfoSha256; - } - else if (hashAlgorithmName == HashAlgorithmName.SHA384) + switch (hashAlgorithmName.Name) { - digestLengthInBytes = SHA384.HashSizeInBytes; - return DigestInfoSha384; - } - else if (hashAlgorithmName == HashAlgorithmName.SHA512) - { - digestLengthInBytes = SHA512.HashSizeInBytes; - return DigestInfoSha512; - } - else - { - Debug.Fail("Unknown digest algorithm"); - throw new CryptographicException(); + case HashAlgorithmNames.MD5: + digestLengthInBytes = MD5.HashSizeInBytes; + return DigestInfoMD5; + case HashAlgorithmNames.SHA1: + digestLengthInBytes = SHA1.HashSizeInBytes; + return DigestInfoSha1; + case HashAlgorithmNames.SHA256: + digestLengthInBytes = SHA256.HashSizeInBytes; + return DigestInfoSha256; + case HashAlgorithmNames.SHA384: + digestLengthInBytes = SHA384.HashSizeInBytes; + return DigestInfoSha384; + case HashAlgorithmNames.SHA512: + digestLengthInBytes = SHA512.HashSizeInBytes; + return DigestInfoSha512; + case HashAlgorithmNames.SHA3_256: + digestLengthInBytes = SHA3_256.HashSizeInBytes; + return DigestInfoSha3_256; + case HashAlgorithmNames.SHA3_384: + digestLengthInBytes = SHA3_384.HashSizeInBytes; + return DigestInfoSha3_384; + case HashAlgorithmNames.SHA3_512: + digestLengthInBytes = SHA3_512.HashSizeInBytes; + return DigestInfoSha3_512; + default: + Debug.Fail("Unknown digest algorithm"); + throw new CryptographicException(); } } diff --git a/src/libraries/Common/src/System/Security/Cryptography/SP800108HmacCounterKdf.cs b/src/libraries/Common/src/System/Security/Cryptography/SP800108HmacCounterKdf.cs index 6598136dfe7a77..a9f37b0fb11a4e 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/SP800108HmacCounterKdf.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/SP800108HmacCounterKdf.cs @@ -559,6 +559,26 @@ private static void CheckHashAlgorithm(HashAlgorithmName hashAlgorithm) case HashAlgorithmNames.SHA384: case HashAlgorithmNames.SHA512: break; +#if NET8_0_OR_GREATER + case HashAlgorithmNames.SHA3_256: + if (!HMACSHA3_256.IsSupported) + { + throw new PlatformNotSupportedException(); + } + break; + case HashAlgorithmNames.SHA3_384: + if (!HMACSHA3_384.IsSupported) + { + throw new PlatformNotSupportedException(); + } + break; + case HashAlgorithmNames.SHA3_512: + if (!HMACSHA3_512.IsSupported) + { + throw new PlatformNotSupportedException(); + } + break; +#endif default: throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmName)); } diff --git a/src/libraries/Common/src/System/Security/Cryptography/SP800108HmacCounterKdfImplementationCng.cs b/src/libraries/Common/src/System/Security/Cryptography/SP800108HmacCounterKdfImplementationCng.cs index ca8f72c61428aa..46143f15c86acc 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/SP800108HmacCounterKdfImplementationCng.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/SP800108HmacCounterKdfImplementationCng.cs @@ -193,7 +193,7 @@ private static unsafe SafeBCryptKeyHandle CreateSymmetricKey(byte* symmetricKey, private static int GetHashBlockSize(string hashAlgorithmName) { - // Block sizes per NIST FIPS pub 180-4. + // Block sizes per NIST FIPS pub 180-4 and FIPS 202. switch (hashAlgorithmName) { case HashAlgorithmNames.SHA1: @@ -202,6 +202,12 @@ private static int GetHashBlockSize(string hashAlgorithmName) case HashAlgorithmNames.SHA384: case HashAlgorithmNames.SHA512: return 1024 / 8; + case HashAlgorithmNames.SHA3_256: + return 1088 / 8; + case HashAlgorithmNames.SHA3_384: + return 832 / 8; + case HashAlgorithmNames.SHA3_512: + return 576 / 8; default: Debug.Fail($"Unexpected hash algorithm '{hashAlgorithmName}'"); throw new CryptographicException(); diff --git a/src/libraries/Common/src/System/Threading/AsyncOverSyncWithIoCancellation.cs b/src/libraries/Common/src/System/Threading/AsyncOverSyncWithIoCancellation.cs index ac13cb07903f06..9285def9f15d83 100644 --- a/src/libraries/Common/src/System/Threading/AsyncOverSyncWithIoCancellation.cs +++ b/src/libraries/Common/src/System/Threading/AsyncOverSyncWithIoCancellation.cs @@ -14,7 +14,7 @@ namespace System.Threading /// /// Helper for performing asynchronous I/O on Windows implemented as queueing a work item that performs synchronous I/O, complete with cancellation support. /// - internal sealed class AsyncOverSyncWithIoCancellation : IThreadPoolWorkItem, ICriticalNotifyCompletion + internal sealed class AsyncOverSyncWithIoCancellation { /// A thread handle for the current OS thread. /// This is lazily-initialized for the current OS thread. We rely on finalization to clean up after it when the thread goes away. @@ -32,23 +32,9 @@ internal sealed class AsyncOverSyncWithIoCancellation : IThreadPoolWorkItem, ICr /// the callback wasn't and will never be invoked. If it's non-null, its completion represents the completion of the asynchronous callback. /// private volatile Task? CallbackCompleted; - /// The continuation object handed to this instance when used as an awaiter to scheduler work to the thread pool. - private Action? _continuation; - - // awaitable / awaiter implementation that enables this instance to be awaited in order to queue - // execution to the thread pool. This is purely a cost-saving measure in order to reuse this - // object we already need as the queued work item. - public AsyncOverSyncWithIoCancellation GetAwaiter() => this; - public bool IsCompleted => false; - public void GetResult() { } - public void OnCompleted(Action continuation) => throw new NotSupportedException(); - public void UnsafeOnCompleted(Action continuation) - { - Debug.Assert(_continuation is null); - _continuation = continuation; - ThreadPool.UnsafeQueueUserWorkItem(this, preferLocal: true); - } - void IThreadPoolWorkItem.Execute() => _continuation!(); + + /// Prevent external instantiation. + private AsyncOverSyncWithIoCancellation() { } /// Queues the invocation of to the thread pool. /// The type of the state passed to . @@ -65,27 +51,24 @@ public void UnsafeOnCompleted(Action continuation) [AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder))] public static async ValueTask InvokeAsync(Action action, TState state, CancellationToken cancellationToken) { - // Create the work item state object. This is used to pass around state through various APIs, - // while also serving double duty as the work item used to queue the operation to the thread pool. - var workItem = new AsyncOverSyncWithIoCancellation(); - - // Queue the work to the thread pool. This is implemented as a custom awaiter that queues the - // awaiter itself to the thread pool. - await workItem; + // Queue the work to complete asynchronously. + await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); // Register for cancellation, perform the work, and clean up. Even though we're in an async method, awaits _must not_ be used inside // the using block, or else the I/O cancellation could both not work and negatively interact with I/O on another thread. The func // _must_ be invoked on the same thread that invoked RegisterCancellation, with no intervening work. - await using (workItem.RegisterCancellation(cancellationToken).ConfigureAwait(false)) + SyncAsyncWorkItemRegistration reg = RegisterCancellation(cancellationToken); + try { - try - { - action(state); - } - catch (OperationCanceledException oce) when (cancellationToken.IsCancellationRequested && oce.CancellationToken != cancellationToken) - { - throw CreateAppropriateCancellationException(cancellationToken, oce); - } + action(state); + } + catch (OperationCanceledException oce) when (cancellationToken.IsCancellationRequested && oce.CancellationToken != cancellationToken) + { + throw CreateAppropriateCancellationException(cancellationToken, oce); + } + finally + { + await reg.DisposeAsync().ConfigureAwait(false); } } @@ -105,27 +88,24 @@ public static async ValueTask InvokeAsync(Action action, TState [AsyncMethodBuilder(typeof(PoolingAsyncValueTaskMethodBuilder<>))] public static async ValueTask InvokeAsync(Func func, TState state, CancellationToken cancellationToken) { - // Create the work item state object. This is used to pass around state through various APIs, - // while also serving double duty as the work item used to queue the operation to the thread pool. - var workItem = new AsyncOverSyncWithIoCancellation(); - - // Queue the work to the thread pool. This is implemented as a custom awaiter that queues the - // awaiter itself to the thread pool. - await workItem; + // Queue the work to complete asynchronously. + await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); // Register for cancellation, perform the work, and clean up. Even though we're in an async method, awaits _must not_ be used inside // the using block, or else the I/O cancellation could both not work and negatively interact with I/O on another thread. The func // _must_ be invoked on the same thread that invoked RegisterCancellation, with no intervening work. - await using (workItem.RegisterCancellation(cancellationToken).ConfigureAwait(false)) + SyncAsyncWorkItemRegistration reg = RegisterCancellation(cancellationToken); + try { - try - { - return func(state); - } - catch (OperationCanceledException oce) when (cancellationToken.IsCancellationRequested && oce.CancellationToken != cancellationToken) - { - throw CreateAppropriateCancellationException(cancellationToken, oce); - } + return func(state); + } + catch (OperationCanceledException oce) when (cancellationToken.IsCancellationRequested && oce.CancellationToken != cancellationToken) + { + throw CreateAppropriateCancellationException(cancellationToken, oce); + } + finally + { + await reg.DisposeAsync().ConfigureAwait(false); } } @@ -145,7 +125,7 @@ private static OperationCanceledException CreateAppropriateCancellationException return newOce; } - /// The struct IDisposable returned from in order to clean up after the registration. + /// The struct IDisposable returned from RegisterCancellation in order to clean up after the registration. private struct SyncAsyncWorkItemRegistration : IDisposable, IAsyncDisposable { public AsyncOverSyncWithIoCancellation WorkItem; @@ -201,44 +181,44 @@ public async ValueTask DisposeAsync() /// Registers for cancellation with the specified token. /// Upon cancellation being requested, the implementation will attempt to CancelSynchronousIo for the thread calling RegisterCancellation. - private SyncAsyncWorkItemRegistration RegisterCancellation(CancellationToken cancellationToken) - { - // If the token can't be canceled, there's nothing to register. - if (!cancellationToken.CanBeCanceled) - { - return default; - } + private static SyncAsyncWorkItemRegistration RegisterCancellation(CancellationToken cancellationToken) => + cancellationToken.CanBeCanceled ? RegisterCancellation(new AsyncOverSyncWithIoCancellation(), cancellationToken) : + default; // If the token can't be canceled, there's nothing to register. + /// Registers for cancellation with the specified token. + /// Upon cancellation being requested, the implementation will attempt to CancelSynchronousIo for the thread calling RegisterCancellation. + private static SyncAsyncWorkItemRegistration RegisterCancellation(AsyncOverSyncWithIoCancellation instance, CancellationToken cancellationToken) + { // Get a handle for the current thread. This is stored and used to cancel the I/O on this thread // in response to the cancellation token having cancellation requested. If the handle is invalid, // which could happen if OpenThread fails, skip attempts at cancellation. The handle needs to be // opened with THREAD_TERMINATE in order to be able to call CancelSynchronousIo. - ThreadHandle = t_currentThreadHandle; - if (ThreadHandle is null) + instance.ThreadHandle = t_currentThreadHandle; + if (instance.ThreadHandle is null) { - ThreadHandle = Interop.Kernel32.OpenThread(Interop.Kernel32.THREAD_TERMINATE, bInheritHandle: false, Interop.Kernel32.GetCurrentThreadId()); - if (ThreadHandle.IsInvalid) + instance.ThreadHandle = Interop.Kernel32.OpenThread(Interop.Kernel32.THREAD_TERMINATE, bInheritHandle: false, Interop.Kernel32.GetCurrentThreadId()); + if (instance.ThreadHandle.IsInvalid) { int lastError = Marshal.GetLastPInvokeError(); Debug.Fail($"{nameof(Interop.Kernel32.OpenThread)} unexpectedly failed with 0x{lastError:X8}: {Marshal.GetPInvokeErrorMessage(lastError)}"); return default; } - t_currentThreadHandle = ThreadHandle; + t_currentThreadHandle = instance.ThreadHandle; } // Register with the token. SyncAsyncWorkItemRegistration reg = default; - reg.WorkItem = this; + reg.WorkItem = instance; reg.CancellationRegistration = cancellationToken.UnsafeRegister(static s => { - var state = (AsyncOverSyncWithIoCancellation)s!; + var instance = (AsyncOverSyncWithIoCancellation)s!; // If cancellation was already requested when UnsafeRegister was called, it'll invoke // the callback immediately. If we allowed that to loop until cancellation was successful, // we'd deadlock, as we'd never perform the very I/O it was waiting for. As such, if // the callback is invoked prior to be ready for it, we ignore the callback. - if (!state.FinishedCancellationRegistration) + if (!instance.FinishedCancellationRegistration) { return; } @@ -250,17 +230,17 @@ private SyncAsyncWorkItemRegistration RegisterCancellation(CancellationToken can // this looping synchronously, we instead queue the invocation of the looping so that it // runs asynchronously from the Cancel call. Then in order to be able to track its completion, // we store the Task representing that asynchronous work, such that cleanup can wait for the Task. - state.CallbackCompleted = Task.Factory.StartNew(static s => + instance.CallbackCompleted = Task.Factory.StartNew(static s => { - var state = (AsyncOverSyncWithIoCancellation)s!; + var instance = (AsyncOverSyncWithIoCancellation)s!; // Cancel the I/O. If the cancellation happens too early and we haven't yet initiated // the synchronous operation, CancelSynchronousIo will fail with ERROR_NOT_FOUND, and // we'll loop to try again. SpinWait sw = default; - while (state.ContinueTryingToCancel) + while (instance.ContinueTryingToCancel) { - if (Interop.Kernel32.CancelSynchronousIo(state.ThreadHandle!)) + if (Interop.Kernel32.CancelSynchronousIo(instance.ThreadHandle!)) { // Successfully canceled I/O. break; @@ -276,12 +256,12 @@ private SyncAsyncWorkItemRegistration RegisterCancellation(CancellationToken can sw.SpinOnce(); } - }, s, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); - }, this); + }, instance, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); + }, instance); // Now that we've registered with the token, tell the callback it's safe to enter // its cancellation loop if the callback is invoked. - FinishedCancellationRegistration = true; + instance.FinishedCancellationRegistration = true; // And now since cancellation may have been requested and we may have suppressed it // until the previous line, check to see if cancellation has now been requested, and diff --git a/src/libraries/Common/src/System/TimeProvider.cs b/src/libraries/Common/src/System/TimeProvider.cs index d1489826eecc40..a8db64c6739047 100644 --- a/src/libraries/Common/src/System/TimeProvider.cs +++ b/src/libraries/Common/src/System/TimeProvider.cs @@ -16,7 +16,7 @@ public abstract class TimeProvider /// and a timer based on . /// /// - /// If the changes after the object is returned, the change will be reflected in any subsequent operations that retrieve . + /// If the changes after the object is returned, the change will be reflected in any subsequent operations that retrieve . /// public static TimeProvider System { get; } = new SystemTimeProvider(); @@ -274,7 +274,7 @@ private static (uint duration, uint periodTime) CheckAndGetValues(TimeSpan dueTi } /// - /// Used to create a instance returned from and uses the default implementation + /// Used to create a instance returned from and uses the default implementation /// provided by which uses , , , and . /// private sealed class SystemTimeProvider : TimeProvider diff --git a/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs b/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs index 2c7627dd9ac07e..5a2c897571ccf9 100644 --- a/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs +++ b/src/libraries/Common/tests/StreamConformanceTests/System/IO/StreamConformanceTests.cs @@ -603,15 +603,6 @@ protected sealed class CustomTaskScheduler : TaskScheduler protected override IEnumerable GetScheduledTasks() => new Task[0]; } - protected readonly struct JumpToThreadPoolAwaiter : ICriticalNotifyCompletion - { - public JumpToThreadPoolAwaiter GetAwaiter() => this; - public bool IsCompleted => false; - public void OnCompleted(Action continuation) => ThreadPool.QueueUserWorkItem(_ => continuation()); - public void UnsafeOnCompleted(Action continuation) => ThreadPool.UnsafeQueueUserWorkItem(_ => continuation(), null); - public void GetResult() { } - } - protected sealed unsafe class NativeMemoryManager : MemoryManager { private readonly int _length; @@ -2046,9 +2037,7 @@ public static IEnumerable ReadAsync_ContinuesOnCurrentContextIfDesired [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "iOS/tvOS blocks binding to UNIX sockets")] public virtual async Task ReadAsync_ContinuesOnCurrentSynchronizationContextIfDesired(bool flowExecutionContext, bool? continueOnCapturedContext) { - await default(JumpToThreadPoolAwaiter); // escape xunit sync ctx - - using StreamPair streams = await CreateConnectedStreamsAsync(); + using StreamPair streams = await CreateConnectedStreamsAsync().ConfigureAwait(ConfigureAwaitOptions.ForceYielding /* escape xunit sync ctx */); foreach ((Stream writeable, Stream readable) in GetReadWritePairs(streams)) { Assert.Null(SynchronizationContext.Current); @@ -2130,9 +2119,7 @@ public virtual async Task ReadAsync_ContinuesOnCurrentSynchronizationContextIfDe [SkipOnPlatform(TestPlatforms.iOS | TestPlatforms.tvOS, "iOS/tvOS blocks binding to UNIX sockets")] public virtual async Task ReadAsync_ContinuesOnCurrentTaskSchedulerIfDesired(bool flowExecutionContext, bool? continueOnCapturedContext) { - await default(JumpToThreadPoolAwaiter); // escape xunit sync ctx - - using StreamPair streams = await CreateConnectedStreamsAsync(); + using StreamPair streams = await CreateConnectedStreamsAsync().ConfigureAwait(ConfigureAwaitOptions.ForceYielding /* escape xunit sync ctx */); foreach ((Stream writeable, Stream readable) in GetReadWritePairs(streams)) { Assert.Null(SynchronizationContext.Current); 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 6497640809f3ab..84bbea4587eef4 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 @@ -14,6 +14,7 @@ public interface IECDiffieHellmanProvider bool ExplicitCurvesSupported { get; } bool CanDeriveNewPublicKey { get; } bool SupportsRawDerivation { get; } + bool SupportsSha3 { get; } } public static partial class ECDiffieHellmanFactory @@ -45,5 +46,7 @@ public static bool IsCurveValid(Oid oid) public static bool CanDeriveNewPublicKey => s_provider.CanDeriveNewPublicKey; public static bool SupportsRawDerivation => s_provider.SupportsRawDerivation; + + public static bool SupportsSha3 => s_provider.SupportsSha3; } } 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 dfca203f4fa14c..0065092e52aad1 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 @@ -207,56 +207,87 @@ public static void DeriveKeyMaterialEquivalentToDeriveKeyFromHash() public static IEnumerable HashDerivationTestCases() { - return new object[][] + yield return new object[] { - new object[] - { - HashAlgorithmName.SHA256, - null, - null, - "595B71C33D9D40ACD9CA847C47267DAEE7498EEF0B553482FAA45791418AC679", - }, + HashAlgorithmName.SHA256, + null, + null, + "595B71C33D9D40ACD9CA847C47267DAEE7498EEF0B553482FAA45791418AC679", + }; - new object[] - { - HashAlgorithmName.SHA1, - null, - null, - "25E464FAC33F4A5F8786627FB3685F4C31B26327", - }, + yield return new object[] + { + HashAlgorithmName.SHA1, + null, + null, + "25E464FAC33F4A5F8786627FB3685F4C31B26327", + }; - new object[] - { - HashAlgorithmName.SHA256, - "02040608", - null, - "D0F4C42D61E794E508A079822F3069C9F89D9E3385C8E090425FF38927798017", - }, + yield return new object[] + { + HashAlgorithmName.SHA256, + "02040608", + null, + "D0F4C42D61E794E508A079822F3069C9F89D9E3385C8E090425FF38927798017", + }; + + yield return new object[] + { + HashAlgorithmName.SHA256, + null, + "010305", + "20DCB58E2AC4E70B1BF47362B0D1C8B728E27D6575EA9B85106CBE05E1F7D6DB", + }; - new object[] + yield return new object[] + { + HashAlgorithmName.SHA256, + "02040608", + "010305", + "EFC758D39896E9DE96C120B0A74FB751F140BD7F3F4FC3777DC2A530145E01EC", + }; + + yield return new object[] + { + HashAlgorithmName.SHA256, + "010305", + "02040608", + "7DB5520A5D6351595FC286CD53509D964FBB152C289F072581CB5E16EBF319E8", + }; + + if (ECDiffieHellmanFactory.SupportsSha3) + { + // Created with: + // (echo -n -e '\x01\x03\0x05'; openssl pkeyutl -derive -inkey private.key -peerkey public.key; echo -n -e '\x02\x04\0x06\0x08') | openssl dgst -sha3-256 + yield return new object[] { - HashAlgorithmName.SHA256, - null, + HashAlgorithmName.SHA3_256, "010305", - "20DCB58E2AC4E70B1BF47362B0D1C8B728E27D6575EA9B85106CBE05E1F7D6DB", - }, + "02040608", + "2AF6DA738DADF26607513ECB56451B5A476C7D42CFEC89872791B7A6C136A4F9", + }; - new object[] + // Created with: + // (echo -n -e '\x01\x03\0x05'; openssl pkeyutl -derive -inkey private.key -peerkey public.key; echo -n -e '\x02\x04\0x06\0x08') | openssl dgst -sha3-384 + yield return new object[] { - HashAlgorithmName.SHA256, - "02040608", + HashAlgorithmName.SHA3_384, "010305", - "EFC758D39896E9DE96C120B0A74FB751F140BD7F3F4FC3777DC2A530145E01EC", - }, + "02040608", + "EE9C10A3E60EA06296699195B3E338575DA529BA167A7520CA8BF50C86C4A08AB153DD7B97ADEE58CE5A9CAAC2F52ED1", + }; - new object[] + // Created with: + // (echo -n -e '\x01\x03\0x05'; openssl pkeyutl -derive -inkey private.key -peerkey public.key; echo -n -e '\x02\x04\0x06\0x08') | openssl dgst -sha3-512 + yield return new object[] { - HashAlgorithmName.SHA256, + HashAlgorithmName.SHA3_512, "010305", "02040608", - "7DB5520A5D6351595FC286CD53509D964FBB152C289F072581CB5E16EBF319E8", - }, - }; + "3614398AFC4A09B0490E095A7901FEA3C9C217E742064A371F2E04D6363EF864" + + "FE52EEEEA976FEC3FF98DE55D1E78E864F009FD834E1D301FA069BD44F6ECD52", + }; + } } #if NETCOREAPP 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 b8ba791ddd7844..f95fb64aafd3a4 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 @@ -248,71 +248,105 @@ public static void SimpleHmacNullKeyForwardsNull() public static IEnumerable HmacDerivationTestCases() { - return new object[][] + yield return new object[] { - new object[] - { - HashAlgorithmName.SHA256, - null, - null, - null, - "6D7D15C9A08FD47DFDABD3541BE3BBAF93B15FC65D30E6012CCC0B23ED5C43FF", - }, - - new object[] - { - HashAlgorithmName.SHA1, - null, - null, - null, - "39D4B035BC1A1E4108B965689E27BA98ACED8449", - }, - - new object[] - { - HashAlgorithmName.SHA256, - "030609", - null, - null, - "7A4F81BF065CC521AFB162DB4A45CEFC78227178A58632EA53D3E367AB7D1979", - }, + HashAlgorithmName.SHA256, + null, + null, + null, + "6D7D15C9A08FD47DFDABD3541BE3BBAF93B15FC65D30E6012CCC0B23ED5C43FF", + }; - new object[] - { - HashAlgorithmName.SHA256, - null, - "02040608", - "010305", - "DB39A6AC9334701D2DCD508C401C65BC69348F684C85EDDE506950F049668842", - }, + yield return new object[] + { + HashAlgorithmName.SHA1, + null, + null, + null, + "39D4B035BC1A1E4108B965689E27BA98ACED8449", + }; + + yield return new object[] + { + HashAlgorithmName.SHA256, + "030609", + null, + null, + "7A4F81BF065CC521AFB162DB4A45CEFC78227178A58632EA53D3E367AB7D1979", + }; + + yield return new object[] + { + HashAlgorithmName.SHA256, + null, + "02040608", + "010305", + "DB39A6AC9334701D2DCD508C401C65BC69348F684C85EDDE506950F049668842", + }; - new object[] + yield return new object[] + { + HashAlgorithmName.SHA256, + null, + "010305", + "02040608", + "66471DE2655DF9404636F9076F845F0B71A04DDA2BA6F1469EB0F2E9EF57DC33", + }; + + yield return new object[] + { + HashAlgorithmName.SHA256, + "030609", + "02040608", + "010305", + "2F7A31FF9118A6BBF92E268568C634A9F1E244CA8C1A74C864DECC50727B7DEE", + }; + + yield return new object[] + { + HashAlgorithmName.SHA256, + "030609", + "010305", + "02040608", + "AE3CD974F262B199B0859D9F933207D2F6E3E04434D60089FE0BE801ED38D370", + }; + + if (ECDiffieHellmanFactory.SupportsSha3) + { + // Created with: + // (echo -n -e '\x01\x03\0x05'; openssl pkeyutl -derive -inkey private.key -peerkey public.key; echo -n -e '\x02\x04\0x06\0x08') | openssl sha3-256 -mac HMAC -macopt hexkey:030609 + yield return new object[] { - HashAlgorithmName.SHA256, - null, + HashAlgorithmName.SHA3_256, + "030609", "010305", "02040608", - "66471DE2655DF9404636F9076F845F0B71A04DDA2BA6F1469EB0F2E9EF57DC33", - }, + "23E7E5648EF46D537F4159F7F40E686279D89ADFD7EF6CFA110034F42EC8CEF7", + }; - new object[] + // Created with: + // (echo -n -e '\x01\x03\0x05'; openssl pkeyutl -derive -inkey private.key -peerkey public.key; echo -n -e '\x02\x04\0x06\0x08') | openssl sha3-384 -mac HMAC -macopt hexkey:030609 + yield return new object[] { - HashAlgorithmName.SHA256, + HashAlgorithmName.SHA3_384, "030609", - "02040608", "010305", - "2F7A31FF9118A6BBF92E268568C634A9F1E244CA8C1A74C864DECC50727B7DEE", - }, + "02040608", + "FD0F7B11489F641DE0964F81D83EF90E33C46D1628C51FA79A85AD1034A9CAD36F8A38C3925704AC0E404BC6FE50ECA4", + }; - new object[] + // Created with: + // (echo -n -e '\x01\x03\0x05'; openssl pkeyutl -derive -inkey private.key -peerkey public.key; echo -n -e '\x02\x04\0x06\0x08') | openssl sha3-512 -mac HMAC -macopt hexkey:030609 + yield return new object[] { - HashAlgorithmName.SHA256, + HashAlgorithmName.SHA3_512, "030609", "010305", "02040608", - "AE3CD974F262B199B0859D9F933207D2F6E3E04434D60089FE0BE801ED38D370", - }, - }; + "2C32BBFBF8A41118AAD3BAA94C8995B5B027246EA3D972937C1BFD9F460C6492" + + "44EEC68EF570B4BB74B0D3BBD463F18526400A77211B5CB39311CDE21104E209", + }; + } } #if NETCOREAPP 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 aab3429ed745b7..d0c596935ef092 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 @@ -246,6 +246,112 @@ public void ValidateNistP521Sha512() HashAlgorithmName.SHA512); } + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.SupportsSha3))] + public void ValidateNistP256Sha3_256() + { + // From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/P256_SHA3-256.pdf + byte[] msg = "4578616d706c65206f66204543445341207769746820502d323536".HexToByteArray(); + + ECParameters parameters = new ECParameters + { + Curve = ECCurve.NamedCurves.nistP256, + Q = new ECPoint + { + X = "b7e08afdfe94bad3f1dc8c734798ba1c62b3a0ad1e9ea2a38201cd0889bc7a19".HexToByteArray(), + Y = "3603f747959dbf7a4bb226e41928729063adc7ae43529e61b563bbc606cc5e09".HexToByteArray(), + }, + D = "c477f9f65c22cce20657faa5b2d1d8122336f851a508a1ed04e479c34985bf96".HexToByteArray(), + }; + + byte[] signature = ( + // r + "2b42f576d07f4165ff65d1f3b1500f81e44c316f1f0b3ef57325b69aca46104f" + + // s + "0a861c2526900245c73bacb9adaec1a5acb3ba1f7114a3c334fdcd5b7690dadd" + ).HexToByteArray(); + + Validate( + parameters, + EccTestData.GetNistP256ExplicitCurve(), + msg, + signature, + HashAlgorithmName.SHA3_256); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.SupportsSha3))] + public void ValidateNistP384Sha3_384() + { + // From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/P384_SHA3-384.pdf + byte[] msg = "4578616d706c65206f66204543445341207769746820502d333834".HexToByteArray(); + + ECParameters parameters = new ECParameters + { + Curve = ECCurve.NamedCurves.nistP384, + Q = new ECPoint + { + X = ("3bf701bc9e9d36b4d5f1455343f09126f2564390f2b48736" + + "5071243c61e6471fb9d2ab74657b82f9086489d9ef0f5cb5").HexToByteArray(), + Y = ("d1a358eafbf952e68d533855ccbdaa6ff75b137a51014431" + + "99325583552a6295ffe5382d00cfcda30344a9b5b68db855").HexToByteArray(), + }, + D = ("f92c02ed629e4b48c0584b1c6ce3a3e3b4faae4afc6acb04" + + "55e73dfc392e6a0ae393a8565e6b9714d1224b57d83f8a08").HexToByteArray(), + }; + + byte[] signature = ( + // r + "30ea514fc0d38d8208756f068113c7cada9f66a3b40ea3b3" + + "13d040d9b57dd41a332795d02cc7d507fcef9faf01a27088" + + // s + "691b9d4969451a98036d53aa725458602125de74881bbc33" + + "3012ca4fa55bde39d1bf16a6aae3fe4992c567c6e7892337" + ).HexToByteArray(); + + Validate( + parameters, + EccTestData.GetNistP384ExplicitCurve(), + msg, + signature, + HashAlgorithmName.SHA3_384); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.SupportsSha3))] + public void ValidateNistP521Sha3_512() + { + // From https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/P521_SHA3-512.pdf + byte[] msg = "4578616d706c65206f66204543445341207769746820502d353231".HexToByteArray(); + + ECParameters parameters = new ECParameters + { + Curve = ECCurve.NamedCurves.nistP521, + Q = new ECPoint + { + X = ("0098e91eef9a68452822309c52fab453f5f117c1da8ed796b255e9ab8f6410cca1" + + "6e59df403a6bdc6ca467a37056b1e54b3005d8ac030decfeb68df18b171885d5c4").HexToByteArray(), + Y = ("0164350c321aecfc1cca1ba4364c9b15656150b4b78d6a48d7d28e7f31985ef17b" + + "e8554376b72900712c4b83ad668327231526e313f5f092999a4632fd50d946bc2e").HexToByteArray(), + }, + D = ("0100085f47b8e1b8b11b7eb33028c0b2888e304bfc98501955b45bba1478dc184e" + + "eedf09b86a5f7c21994406072787205e69a63709fe35aa93ba333514b24f961722").HexToByteArray(), + }; + + byte[] signature = ( + // r + "0140c8edca57108ce3f7e7a240ddd3ad74d81e2de62451fc1d558fdc79269adacd" + + "1c2526eeeef32f8c0432a9d56e2b4a8a732891c37c9b96641a9254ccfe5dc3e2ba" + + // s + "00b25188492d58e808edebd7bf440ed20db771ca7c618595d5398e1b1c0098e300" + + "d8c803ec69ec5f46c84fc61967a302d366c627fcfa56f87f241ef921b6e627adbf" + ).HexToByteArray(); + + Validate( + parameters, + EccTestData.GetNistP521ExplicitCurve(), + msg, + signature, + HashAlgorithmName.SHA3_512); + } + private static void Validate( ECParameters parameters, ECCurve explicitCurve, diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs index c74a993e54a7b6..5b97f468a4271e 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/EncryptDecrypt.cs @@ -315,7 +315,19 @@ public void RsaCryptRoundtrip_OaepSHA384() => public void RsaCryptRoundtrip_OaepSHA512() => RsaCryptRoundtrip(RSAEncryptionPadding.OaepSHA512, RSAFactory.SupportsSha2Oaep); - private void RsaCryptRoundtrip(RSAEncryptionPadding paddingMode, bool expectSuccess=true) + [Fact] + public void RsaCryptRoundtrip_OaepSHA3_256() => + RsaCryptRoundtrip(RSAEncryptionPadding.OaepSHA3_256, RSAFactory.SupportsSha3); + + [Fact] + public void RsaCryptRoundtrip_OaepSHA3_384() => + RsaCryptRoundtrip(RSAEncryptionPadding.OaepSHA3_384, RSAFactory.SupportsSha3); + + [Fact] + public void RsaCryptRoundtrip_OaepSHA3_512() => + RsaCryptRoundtrip(RSAEncryptionPadding.OaepSHA3_512, RSAFactory.SupportsSha3); + + private void RsaCryptRoundtrip(RSAEncryptionPadding paddingMode, bool expectSuccess = true) { byte[] crypt; byte[] output; @@ -324,9 +336,12 @@ private void RsaCryptRoundtrip(RSAEncryptionPadding paddingMode, bool expectSucc { if (!expectSuccess) { - Assert.ThrowsAny( + Exception ex = Assert.ThrowsAny( () => Encrypt(rsa, TestData.HelloBytes, paddingMode)); + Assert.True(ex is CryptographicException or PlatformNotSupportedException, + "exception is CryptographicException or PlatformNotSupportedException"); + return; } @@ -370,6 +385,13 @@ void RoundtripEmpty(RSAEncryptionPadding paddingMode) RoundtripEmpty(RSAEncryptionPadding.OaepSHA384); RoundtripEmpty(RSAEncryptionPadding.OaepSHA512); } + + if (RSAFactory.SupportsSha3) + { + RoundtripEmpty(RSAEncryptionPadding.OaepSHA3_256); + RoundtripEmpty(RSAEncryptionPadding.OaepSHA3_384); + RoundtripEmpty(RSAEncryptionPadding.OaepSHA3_512); + } } } @@ -715,6 +737,13 @@ public static IEnumerable OaepPaddingModes yield return new object[] { RSAEncryptionPadding.OaepSHA384 }; yield return new object[] { RSAEncryptionPadding.OaepSHA512 }; } + + if (RSAFactory.SupportsSha3) + { + yield return new object[] { RSAEncryptionPadding.OaepSHA3_256 }; + yield return new object[] { RSAEncryptionPadding.OaepSHA3_384 }; + yield return new object[] { RSAEncryptionPadding.OaepSHA3_512 }; + } } } } diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAFactory.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAFactory.cs index 9a4b27348ab4a0..b13a6ee01d8e41 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAFactory.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/RSAFactory.cs @@ -12,6 +12,7 @@ public interface IRSAProvider bool SupportsSha2Oaep { get; } bool SupportsPss { get; } bool SupportsSha1Signatures { get; } + bool SupportsSha3 { get; } } public static partial class RSAFactory @@ -42,5 +43,8 @@ public static RSA Create(RSAParameters rsaParameters) public static bool SupportsPss => s_provider.SupportsPss; public static bool SupportsSha1Signatures => s_provider.SupportsSha1Signatures; + + public static bool SupportsSha3 => s_provider.SupportsSha3; + public static bool NoSupportsSha3 => !SupportsSha3; } } diff --git a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs index 0bbdd7db7372da..6b0fd33bf89e7b 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/AlgorithmImplementations/RSA/SignVerify.cs @@ -504,6 +504,84 @@ public void VerifySignature_SHA256_2048() VerifySignature(signature, TestData.HelloBytes, "SHA256", TestData.RSA2048Params); } + [ConditionalFact(typeof(RSAFactory), nameof(RSAFactory.SupportsSha3))] + public void VerifySignature_SHA3_256_RSA2048() + { + byte[] signature = new byte[] + { + 0x37, 0xfc, 0x5b, 0xa7, 0xcd, 0x72, 0x93, 0x55, 0x43, 0x6f, 0x2c, 0x5c, 0xce, 0x10, 0x20, 0x67, + 0x38, 0xbc, 0x82, 0x65, 0xad, 0x64, 0x41, 0x3d, 0x7b, 0xe1, 0x13, 0x6e, 0xbf, 0x7c, 0x0a, 0xa7, + 0xc7, 0x42, 0x57, 0xf3, 0x75, 0xec, 0xda, 0xf1, 0xa0, 0xeb, 0x6d, 0x61, 0x04, 0x07, 0x4b, 0x3c, + 0xf8, 0x0d, 0x1d, 0x7a, 0xb2, 0x1f, 0xb1, 0xa4, 0xae, 0x35, 0x85, 0x18, 0xe4, 0xe1, 0xa5, 0x66, + 0x3d, 0x0c, 0xcd, 0x60, 0xf6, 0x6c, 0x89, 0xf6, 0x49, 0x87, 0x19, 0x3a, 0xa2, 0x24, 0x8a, 0xd9, + 0x17, 0x58, 0x2e, 0x50, 0x69, 0xd4, 0xae, 0x92, 0x17, 0xc1, 0xf8, 0x8e, 0xae, 0xca, 0x05, 0xc0, + 0x9c, 0x9d, 0xda, 0x0c, 0x82, 0x16, 0xae, 0xa4, 0x73, 0xe7, 0x65, 0x90, 0xb9, 0x25, 0x89, 0xe8, + 0xae, 0x60, 0x74, 0x86, 0x2e, 0xd6, 0xa8, 0x8a, 0x05, 0xda, 0x6c, 0x2e, 0x3f, 0x32, 0x24, 0x84, + 0x23, 0x87, 0x10, 0x5b, 0x42, 0x79, 0xdd, 0x64, 0x2c, 0xe4, 0x60, 0x75, 0x38, 0x2b, 0x37, 0x43, + 0x1c, 0x9b, 0x75, 0x6a, 0xf2, 0xfa, 0xbf, 0x95, 0x7f, 0xdb, 0x64, 0xe0, 0xa6, 0xc0, 0xb1, 0x24, + 0xcb, 0xf9, 0xdc, 0x30, 0xcd, 0xba, 0x54, 0x9a, 0xd4, 0xea, 0x3d, 0xcf, 0x3b, 0x08, 0x97, 0x19, + 0xdd, 0xc1, 0xf0, 0x20, 0xf6, 0x02, 0x7c, 0x0e, 0x0c, 0x84, 0x70, 0x89, 0x78, 0x5c, 0x50, 0xc5, + 0xce, 0xe5, 0xdd, 0x03, 0xf4, 0xc5, 0x86, 0x0e, 0xb7, 0x98, 0xd5, 0x96, 0x98, 0x2e, 0x02, 0xc9, + 0xb0, 0x41, 0x84, 0xa9, 0xa1, 0xda, 0x75, 0x81, 0x1d, 0x5a, 0x6a, 0x00, 0x33, 0x0f, 0x94, 0xa4, + 0x20, 0x0c, 0x91, 0xae, 0xae, 0xa4, 0xd3, 0xa8, 0x95, 0x20, 0x5c, 0x0c, 0x3b, 0x6e, 0x32, 0x7e, + 0xd3, 0x5b, 0xf4, 0x9b, 0x0c, 0xe2, 0x97, 0xd4, 0x1c, 0xf7, 0x98, 0x96, 0x77, 0xda, 0x05, 0xf5, + }; + + VerifySignature(signature, TestData.HelloBytes, HashAlgorithmName.SHA3_256.Name, TestData.RSA2048Params); + } + + [ConditionalFact(typeof(RSAFactory), nameof(RSAFactory.SupportsSha3))] + public void VerifySignature_SHA3_384_RSA2048() + { + byte[] signature = new byte[] + { + 0x96, 0x76, 0xdf, 0xa3, 0xd3, 0xac, 0x74, 0x08, 0x18, 0x41, 0x0a, 0xa1, 0x03, 0x6b, 0x28, 0x5d, + 0xf8, 0xf7, 0xe5, 0x72, 0xe1, 0x7e, 0xb0, 0x11, 0x2f, 0x91, 0xbf, 0xce, 0xba, 0xa1, 0x4e, 0xfa, + 0x6f, 0x20, 0xaa, 0xc7, 0x8d, 0xf4, 0x8a, 0xba, 0xd3, 0xa3, 0x07, 0xa0, 0x0f, 0x09, 0x44, 0x7d, + 0xcc, 0xa1, 0x7b, 0xe4, 0x17, 0xcb, 0xe9, 0xe0, 0x78, 0xff, 0xd0, 0xf2, 0xdf, 0xd1, 0xdb, 0xd3, + 0x4a, 0xfb, 0xa8, 0x11, 0xac, 0xd3, 0x27, 0xcc, 0x05, 0x59, 0xc8, 0x16, 0x5d, 0x15, 0x68, 0x4d, + 0x20, 0x17, 0xd2, 0x52, 0xa1, 0xee, 0x7f, 0xce, 0xdb, 0xd4, 0x1a, 0x18, 0x6a, 0xc1, 0x2e, 0x42, + 0x74, 0xcd, 0xc8, 0x31, 0x92, 0x24, 0x33, 0x7e, 0x41, 0x0b, 0x16, 0xf3, 0xd4, 0xa0, 0x30, 0x78, + 0x8e, 0x3a, 0x05, 0xfa, 0xcb, 0x5b, 0x9f, 0x71, 0xd4, 0xfb, 0x27, 0x17, 0x19, 0x66, 0xe1, 0x05, + 0x6d, 0x3a, 0xd8, 0x89, 0x27, 0x19, 0x4f, 0x28, 0x3f, 0x6c, 0xb9, 0xfe, 0xca, 0xfb, 0x77, 0xcc, + 0xf1, 0x46, 0x2a, 0x3a, 0x74, 0x17, 0x8a, 0xb1, 0x76, 0x3a, 0x1b, 0xc3, 0x2e, 0x29, 0x29, 0xa6, + 0xeb, 0x1e, 0xf5, 0x3d, 0x4a, 0x41, 0x39, 0x49, 0xc3, 0x87, 0xe6, 0xcb, 0x49, 0x81, 0x8c, 0xa9, + 0x8a, 0xd8, 0xf5, 0x9e, 0x1c, 0x96, 0x8f, 0xac, 0xc4, 0xac, 0xd3, 0x1b, 0x7a, 0x09, 0x33, 0x48, + 0x62, 0xcc, 0x13, 0x3b, 0xb6, 0x9c, 0x20, 0x55, 0xb3, 0x3c, 0x0b, 0x77, 0xc5, 0x0e, 0x3d, 0x26, + 0x41, 0x15, 0xbf, 0xf7, 0xea, 0xdf, 0x44, 0x9c, 0x35, 0x0b, 0xca, 0x2e, 0x6e, 0xac, 0x04, 0x34, + 0x52, 0x18, 0x68, 0xa0, 0xc8, 0x3b, 0x51, 0xfb, 0x67, 0xed, 0x89, 0x29, 0x1e, 0xe4, 0xfe, 0xb3, + 0x78, 0xb1, 0x40, 0xe3, 0xd3, 0x53, 0xf4, 0x3e, 0xa5, 0x07, 0x33, 0x83, 0xf7, 0x02, 0x39, 0x1b, + }; + + VerifySignature(signature, TestData.HelloBytes, HashAlgorithmName.SHA3_384.Name, TestData.RSA2048Params); + } + + [ConditionalFact(typeof(RSAFactory), nameof(RSAFactory.SupportsSha3))] + public void VerifySignature_SHA3_512_RSA2048() + { + byte[] signature = new byte[] + { + 0x18, 0x83, 0xab, 0x01, 0xc1, 0xaf, 0x98, 0xa9, 0xc2, 0xde, 0x2d, 0x63, 0x4f, 0x8a, 0xf6, 0x47, + 0xd9, 0xd2, 0xd1, 0xa0, 0x5b, 0xf4, 0x14, 0x6a, 0x49, 0x14, 0x56, 0x90, 0x63, 0xf9, 0x2c, 0xf6, + 0xed, 0xc2, 0x19, 0x65, 0x80, 0x0b, 0xa9, 0x7a, 0xa9, 0xcc, 0x00, 0x93, 0xdc, 0x8c, 0xcd, 0xef, + 0xa1, 0x76, 0x4c, 0x56, 0x8c, 0x36, 0x25, 0xcb, 0xbe, 0xd2, 0xbf, 0x49, 0xe6, 0xac, 0xbe, 0x50, + 0x52, 0xf8, 0xd0, 0xf9, 0xb0, 0xcb, 0xfb, 0xae, 0x41, 0x8b, 0x94, 0xbc, 0x47, 0xee, 0x71, 0x1d, + 0x9e, 0x4b, 0xcc, 0x6b, 0xe2, 0x66, 0x01, 0x92, 0x16, 0x06, 0x43, 0x64, 0x65, 0x19, 0x3a, 0xed, + 0x5f, 0x60, 0x85, 0xb1, 0xa8, 0x29, 0x76, 0x17, 0x2d, 0xb3, 0xc5, 0xee, 0x6d, 0x76, 0xef, 0x14, + 0xf8, 0x47, 0x8b, 0x35, 0x32, 0x4e, 0x8f, 0x79, 0xa8, 0x02, 0xe1, 0xe6, 0x49, 0xda, 0x50, 0x98, + 0xd7, 0xb9, 0x71, 0xf6, 0x9d, 0x9b, 0xcd, 0xb6, 0x0d, 0xd3, 0xc8, 0x9d, 0xf2, 0xac, 0xfa, 0xad, + 0xd4, 0xb6, 0xc2, 0x72, 0x9f, 0x14, 0xce, 0x24, 0x87, 0x68, 0x47, 0x6d, 0x7a, 0x73, 0xce, 0x67, + 0xb2, 0xd5, 0x07, 0x69, 0x0d, 0xc3, 0xdd, 0xb4, 0xc2, 0x56, 0xbc, 0x10, 0xc2, 0xe5, 0x9d, 0xb3, + 0xf9, 0x4d, 0xcd, 0xef, 0x9f, 0xe3, 0x3b, 0x8c, 0x49, 0xdf, 0x4b, 0x1f, 0xc0, 0x0c, 0x2d, 0xf6, + 0xad, 0x6c, 0x0f, 0x83, 0x5c, 0x74, 0xb0, 0xff, 0x95, 0x7f, 0x37, 0x34, 0x7b, 0x07, 0x50, 0x91, + 0x7f, 0xd2, 0x26, 0x39, 0x1f, 0xad, 0x72, 0x8a, 0x47, 0x2e, 0x6c, 0xb4, 0xf2, 0xcd, 0x09, 0xfd, + 0x1b, 0xca, 0xf6, 0xbe, 0x70, 0x14, 0xe8, 0x51, 0x1e, 0xf4, 0x5b, 0xd9, 0x57, 0xa6, 0x73, 0xe2, + 0xa0, 0xde, 0xc4, 0x67, 0x7a, 0x4a, 0xe2, 0x24, 0x64, 0x79, 0xd5, 0xe7, 0x39, 0xfc, 0xb2, 0xd9, + }; + + VerifySignature(signature, TestData.HelloBytes, HashAlgorithmName.SHA3_512.Name, TestData.RSA2048Params); + } + [Theory] [MemberData(nameof(RoundTripTheories))] public void SignAndVerify_Roundtrip(string hashAlgorithm, RSAParameters rsaParameters) @@ -877,19 +955,10 @@ public void VerifyHashSignature_SHA256_2048() VerifyHashSignature(hashSignature, dataHash, "SHA256", TestData.RSA2048Params); } - [ConditionalTheory] - [InlineData("SHA256")] - [InlineData("SHA384")] - [InlineData("SHA512")] - [InlineData("MD5")] - [InlineData("SHA1")] + [Theory] + [MemberData(nameof(HashAlgorithmNames))] public void PssRoundtrip(string hashAlgorithmName) { - if (!RSAFactory.SupportsSha1Signatures && hashAlgorithmName == "SHA1") - { - throw new SkipTestException("Platform does not support RSA with SHA1 signatures."); - } - RSAParameters privateParameters = TestData.RSA2048Params; RSAParameters publicParameters = new RSAParameters { @@ -1062,6 +1131,150 @@ public void VerifyExpectedSignature_PssSha512() helloSignature); } + [ConditionalFact(typeof(RSAFactory), nameof(RSAFactory.SupportsSha3))] + public void VerifyExpectedSignature_PssSha3_256() + { + // Signature independently created with + // echo -n Hello | openssl dgst -sha3-256 -binary | openssl pkeyutl -sign -inkey key.pem -pkeyopt rsa_padding_mode:pss -pkeyopt digest:sha3-256 | xxd -i -c 16 + byte[] helloSignature = + { + 0x0b, 0x02, 0x36, 0x0c, 0x56, 0x6b, 0x93, 0xa8, 0x4e, 0x4d, 0x0e, 0xa3, 0x67, 0x28, 0xc6, 0xea, + 0xdb, 0x05, 0xc8, 0x63, 0x64, 0xe5, 0xec, 0xf9, 0xc1, 0x25, 0x5a, 0x34, 0xe6, 0x3f, 0xe1, 0x38, + 0x49, 0x45, 0x0b, 0x34, 0x6b, 0xa7, 0x91, 0xe1, 0x22, 0xe0, 0x2c, 0x8d, 0x46, 0x23, 0x38, 0xb1, + 0x9e, 0x4c, 0xf3, 0xa0, 0xff, 0x57, 0x96, 0x01, 0xbb, 0xa4, 0x0f, 0x03, 0x27, 0xaf, 0x8e, 0x99, + 0x5e, 0x0e, 0x99, 0xfd, 0xc6, 0x55, 0x81, 0x65, 0x56, 0x83, 0x2d, 0x42, 0xa3, 0x60, 0xc3, 0x36, + 0x69, 0xb4, 0x39, 0x04, 0x70, 0xfe, 0x26, 0x9b, 0x65, 0x6a, 0x15, 0xaa, 0xfc, 0xc5, 0x70, 0x71, + 0xba, 0x01, 0x49, 0xae, 0x27, 0xd4, 0x52, 0x28, 0xe4, 0xce, 0x37, 0x8a, 0x7d, 0x16, 0x2f, 0x59, + 0x3a, 0x1d, 0x36, 0x44, 0x82, 0xba, 0x51, 0xa3, 0x2c, 0xf9, 0x7e, 0xad, 0x36, 0xd4, 0x24, 0xfb, + 0x77, 0xae, 0x55, 0x10, 0x6e, 0xbc, 0x9d, 0xc8, 0xd7, 0xf4, 0x2b, 0x07, 0x70, 0x20, 0x8e, 0xd4, + 0xc6, 0xb3, 0x7f, 0x72, 0x9e, 0xa7, 0x0e, 0xd5, 0x31, 0x5d, 0x8c, 0x0c, 0xca, 0xae, 0x5a, 0x5a, + 0x38, 0x10, 0x42, 0x9f, 0x4f, 0x64, 0xc8, 0xe3, 0xdb, 0x4c, 0x17, 0x0b, 0x7b, 0x97, 0x82, 0x1f, + 0x9c, 0x88, 0xcf, 0x5e, 0xe7, 0x19, 0x8f, 0xa9, 0x5f, 0xd0, 0x1b, 0x19, 0x21, 0x2a, 0x2d, 0x36, + 0x45, 0x4a, 0xb1, 0x4d, 0xc8, 0xe1, 0x5e, 0x53, 0x24, 0xe1, 0x0b, 0x03, 0x01, 0x5d, 0xd9, 0x8f, + 0xe3, 0x3a, 0xdb, 0x3f, 0xbf, 0xa4, 0x24, 0x16, 0x44, 0x3e, 0x52, 0x5c, 0x6c, 0xfd, 0x2d, 0x0e, + 0x22, 0x69, 0xcf, 0x2a, 0x58, 0x8f, 0xe7, 0x31, 0x88, 0x22, 0xb8, 0x21, 0x68, 0x56, 0x6b, 0xb6, + 0xab, 0x76, 0x81, 0x41, 0x59, 0xb9, 0xe5, 0xc2, 0x61, 0x06, 0xea, 0x9b, 0x5b, 0x57, 0xf7, 0xb0, + }; + + VerifyExpectedSignature_Pss( + TestData.RSA2048Params, + HashAlgorithmName.SHA3_256, + TestData.HelloBytes, + helloSignature); + } + + [ConditionalFact(typeof(RSAFactory), nameof(RSAFactory.SupportsSha3))] + public void VerifyExpectedSignature_PssSha3_384() + { + // Signature independently created with + // echo -n Hello | openssl dgst -sha3-384 -binary | openssl pkeyutl -sign -inkey key.pem -pkeyopt rsa_padding_mode:pss -pkeyopt digest:sha3-384 | xxd -i -c 16 + byte[] helloSignature = + { + 0x75, 0x00, 0x1d, 0xa9, 0x3b, 0xfa, 0x79, 0x57, 0x4a, 0x3c, 0x9f, 0xec, 0x7b, 0xa4, 0x1f, 0x17, + 0x3a, 0x32, 0x20, 0x90, 0x62, 0x16, 0x25, 0xae, 0x80, 0x54, 0x71, 0xb0, 0xf5, 0x28, 0x5c, 0x97, + 0xfc, 0x4c, 0x21, 0x18, 0xb0, 0xfb, 0x90, 0xae, 0xca, 0xa6, 0x76, 0xf5, 0x14, 0x7a, 0x23, 0x47, + 0x39, 0x1c, 0xf4, 0x62, 0x23, 0x82, 0x18, 0x72, 0x58, 0x64, 0x9a, 0xe2, 0x3b, 0x4e, 0x5a, 0xe5, + 0xf1, 0x16, 0x77, 0xe4, 0xbe, 0xb5, 0x90, 0x54, 0x34, 0x38, 0x24, 0xe4, 0xe1, 0x59, 0xd2, 0x58, + 0x82, 0xc3, 0x68, 0x95, 0xb0, 0x1a, 0x0e, 0x1a, 0x67, 0x4a, 0x28, 0x1e, 0x7e, 0x5c, 0x67, 0xd2, + 0x2e, 0x9c, 0xb6, 0x12, 0x29, 0xf4, 0x57, 0x62, 0xaa, 0xf6, 0x46, 0x00, 0x90, 0xee, 0xc1, 0xb8, + 0x06, 0x40, 0x41, 0x8d, 0xc4, 0x69, 0x68, 0x75, 0xc5, 0xfc, 0xbc, 0x73, 0x40, 0x7c, 0xd6, 0xef, + 0xd0, 0x28, 0xe7, 0x32, 0x52, 0x34, 0x2d, 0x43, 0xca, 0xb8, 0x1e, 0x80, 0x07, 0x1c, 0xe6, 0x54, + 0xd9, 0x03, 0x06, 0xc0, 0xc7, 0x1a, 0x5a, 0xaf, 0x1a, 0xf3, 0xaa, 0xce, 0xa4, 0x02, 0xff, 0xf5, + 0xed, 0x7e, 0x0b, 0x2a, 0x68, 0x7d, 0x65, 0x98, 0xf4, 0xf4, 0x82, 0x3f, 0x54, 0x2a, 0x18, 0x02, + 0xf9, 0x3e, 0x3d, 0xed, 0x18, 0x98, 0xd5, 0xb2, 0x5f, 0x7f, 0xee, 0x26, 0xa1, 0x8f, 0xf5, 0x39, + 0x97, 0xeb, 0x71, 0x18, 0xf1, 0x3c, 0x10, 0x49, 0x34, 0x2e, 0xa8, 0x92, 0x50, 0x17, 0xb7, 0x91, + 0x6b, 0x66, 0x67, 0x2b, 0xd1, 0x73, 0x0b, 0x73, 0xa3, 0xc5, 0xef, 0x03, 0x70, 0xbc, 0x38, 0x59, + 0x1d, 0x23, 0xa2, 0xf8, 0x2d, 0xae, 0x43, 0xc8, 0x6d, 0x10, 0x2c, 0x56, 0x48, 0x2a, 0xc7, 0xef, + 0xf2, 0x4e, 0x5c, 0x30, 0x75, 0xbc, 0xd3, 0xd6, 0x4c, 0xfd, 0x45, 0xc6, 0x43, 0xca, 0xe8, 0x73, + }; + + VerifyExpectedSignature_Pss( + TestData.RSA2048Params, + HashAlgorithmName.SHA3_384, + TestData.HelloBytes, + helloSignature); + } + + [ConditionalFact(typeof(RSAFactory), nameof(RSAFactory.SupportsSha3))] + public void VerifyExpectedSignature_PssSha3_512() + { + // Signature independently created with + // echo -n Hello | openssl dgst -sha3-512 -binary | openssl pkeyutl -sign -inkey key.pem -pkeyopt rsa_padding_mode:pss -pkeyopt digest:sha3-512 | xxd -i -c 16 + byte[] helloSignature = + { + 0x2b, 0x02, 0x93, 0xd1, 0x56, 0x1d, 0x03, 0xce, 0xc7, 0xe0, 0xd0, 0x76, 0xf7, 0xce, 0x76, 0xd7, + 0xd6, 0xf1, 0xeb, 0xc2, 0xc4, 0x97, 0xee, 0x16, 0xdb, 0x04, 0x9c, 0x51, 0xd3, 0xc4, 0x76, 0xcd, + 0xdb, 0x77, 0x3f, 0x82, 0xf1, 0x31, 0x56, 0x77, 0xc8, 0x44, 0xfd, 0x29, 0x42, 0xf0, 0x68, 0x5d, + 0x27, 0x11, 0x74, 0xc1, 0x44, 0x4e, 0x30, 0x6e, 0xfc, 0x3c, 0xa8, 0x61, 0x14, 0x1d, 0x84, 0xec, + 0x92, 0x2c, 0x80, 0xeb, 0x57, 0xd0, 0x81, 0xe7, 0xae, 0xf7, 0x83, 0xe1, 0xe6, 0xfb, 0xc6, 0xed, + 0x5e, 0x0a, 0xd8, 0x67, 0x01, 0xf4, 0xc8, 0x8d, 0x27, 0x7c, 0x5f, 0xff, 0xb7, 0x9d, 0xb4, 0xd4, + 0x70, 0x18, 0xd4, 0x94, 0x7d, 0x36, 0xa7, 0x63, 0xe1, 0xa2, 0x30, 0x53, 0x6a, 0xef, 0x6e, 0xfa, + 0xad, 0xf4, 0xfd, 0xea, 0xba, 0x81, 0xd9, 0x73, 0x75, 0x90, 0xff, 0x98, 0x4c, 0xdb, 0x7d, 0xc6, + 0x91, 0xd9, 0x83, 0xdf, 0x31, 0xa3, 0xb4, 0x05, 0x91, 0xf9, 0xbe, 0x96, 0xfc, 0xed, 0xfd, 0x8b, + 0x8e, 0x9a, 0xee, 0xe5, 0xaf, 0xfd, 0x7e, 0x7e, 0xe0, 0xe1, 0x65, 0xa4, 0xf1, 0xdb, 0x4f, 0x01, + 0x47, 0x00, 0xee, 0x03, 0xb7, 0x96, 0x4c, 0x73, 0xdc, 0x6f, 0xf8, 0xf9, 0xac, 0xce, 0x1e, 0x4b, + 0xb8, 0x3d, 0x5b, 0xd5, 0xea, 0xf1, 0x4b, 0xd9, 0x63, 0x45, 0x2a, 0x49, 0x22, 0x2d, 0x6c, 0xc5, + 0x48, 0xe3, 0x1d, 0xbd, 0x92, 0xed, 0x42, 0x5a, 0x0c, 0xde, 0xb3, 0x2b, 0x91, 0xbd, 0x8e, 0x74, + 0x59, 0x6c, 0x9c, 0x39, 0x24, 0x43, 0xe4, 0x5c, 0xf6, 0x26, 0xd6, 0x30, 0xa0, 0x53, 0xb5, 0x2a, + 0x0d, 0x0d, 0xfc, 0x68, 0xb5, 0xae, 0x8d, 0x7e, 0xdf, 0x45, 0xfc, 0x66, 0x43, 0x93, 0x8d, 0x40, + 0x42, 0x29, 0xe1, 0xe9, 0xe3, 0xff, 0xda, 0xd8, 0x7d, 0x64, 0x9a, 0x26, 0xea, 0xb3, 0xba, 0x7d, + }; + + VerifyExpectedSignature_Pss( + TestData.RSA2048Params, + HashAlgorithmName.SHA3_512, + TestData.HelloBytes, + helloSignature); + } + + [ConditionalTheory(typeof(RSAFactory), nameof(RSAFactory.NoSupportsSha3))] + [InlineData("SHA3-256")] + [InlineData("SHA3-384")] + [InlineData("SHA3-512")] + public void Pkcs1UnsupportedHashAlgorithm(string hashAlgorithm) + { + using (RSA rsa = RSAFactory.Create()) + { + Exception ex = Assert.ThrowsAny(() => + SignData(rsa, new byte[] { 1 }, new HashAlgorithmName(hashAlgorithm), RSASignaturePadding.Pkcs1)); + + Assert.True( + ex is PlatformNotSupportedException or CryptographicException, + "ex is PlatformNotSupportedException or CryptographicException"); + + ex = Assert.ThrowsAny(() => + VerifyData(rsa, new byte[] { 1 }, new byte[] { 1 }, new HashAlgorithmName(hashAlgorithm), RSASignaturePadding.Pkcs1)); + + Assert.True( + ex is PlatformNotSupportedException or CryptographicException, + "ex is PlatformNotSupportedException or CryptographicException"); + } + } + + [ConditionalTheory(typeof(RSAFactory), nameof(RSAFactory.NoSupportsSha3))] + [InlineData("SHA3-256")] + [InlineData("SHA3-384")] + [InlineData("SHA3-512")] + public void PssUnsupportedHashAlgorithm(string hashAlgorithm) + { + using (RSA rsa = RSAFactory.Create()) + { + Exception ex = Assert.ThrowsAny(() => + SignData(rsa, new byte[] { 1 }, new HashAlgorithmName(hashAlgorithm), RSASignaturePadding.Pss)); + + Assert.True( + ex is CryptographicException or PlatformNotSupportedException, + "ex is CryptographicException or PlatformNotSupportedException"); + + ex = Assert.ThrowsAny(() => + VerifyData(rsa, new byte[] { 1 }, new byte[] { 1 }, new HashAlgorithmName(hashAlgorithm), RSASignaturePadding.Pss)); + + Assert.True( + ex is CryptographicException or PlatformNotSupportedException, + "ex is CryptographicException or PlatformNotSupportedException"); + } + } + private void VerifyExpectedSignature_Pss( RSAParameters keyParameters, HashAlgorithmName hashAlgorithm, @@ -1314,5 +1527,28 @@ private void SignAndVerify(byte[] data, string hashAlgorithmName, RSAParameters Assert.True(signatureMatched); } } + + public static IEnumerable HashAlgorithmNames + { + get + { + yield return new object[] { HashAlgorithmName.SHA256.Name }; + yield return new object[] { HashAlgorithmName.SHA384.Name }; + yield return new object[] { HashAlgorithmName.SHA512.Name }; + yield return new object[] { HashAlgorithmName.MD5.Name }; + + if (RSAFactory.SupportsSha1Signatures) + { + yield return new object[] { HashAlgorithmName.SHA1.Name }; + } + + if (RSAFactory.SupportsSha3) + { + yield return new object[] { HashAlgorithmName.SHA3_256.Name }; + yield return new object[] { HashAlgorithmName.SHA3_384.Name }; + yield return new object[] { HashAlgorithmName.SHA3_512.Name }; + } + } + } } } diff --git a/src/libraries/Common/tests/System/Security/Cryptography/SP800108HmacCounterKdfTests.Functional.cs b/src/libraries/Common/tests/System/Security/Cryptography/SP800108HmacCounterKdfTests.Functional.cs index 338ffc7a2a6527..5eb6d097026c65 100644 --- a/src/libraries/Common/tests/System/Security/Cryptography/SP800108HmacCounterKdfTests.Functional.cs +++ b/src/libraries/Common/tests/System/Security/Cryptography/SP800108HmacCounterKdfTests.Functional.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Globalization; +using Microsoft.DotNet.XUnitExtensions; using Xunit; namespace System.Security.Cryptography.Tests @@ -81,7 +82,7 @@ public static void EmptyTests(byte[] key, string label, string context, byte[] e VerifyKbkdf(expected, key, HashAlgorithmName.SHA256, label.ToCharArray(), context.ToCharArray()); } - [Theory] + [ConditionalTheory] [InlineData(nameof(HashAlgorithmName.SHA1), 512 / 8 - 1, new byte[] { 0xc9, 0x0f, 0x9d, 0x91, 0x85, 0xe5, 0xeb, 0x9b })] [InlineData(nameof(HashAlgorithmName.SHA1), 512 / 8, new byte[] { 0x7b, 0xdb, 0x38, 0x28, 0xc0, 0x9f, 0x49, 0x05 })] [InlineData(nameof(HashAlgorithmName.SHA1), 512 / 8 + 1, new byte[] { 0x6c, 0x3a, 0xba, 0x28, 0x38, 0xad, 0x51, 0x2c })] @@ -94,8 +95,28 @@ public static void EmptyTests(byte[] key, string label, string context, byte[] e [InlineData(nameof(HashAlgorithmName.SHA512), 1024 / 8 - 1, new byte[] { 0xa4, 0xe5, 0x24, 0xe8, 0x56, 0x2b, 0x48, 0xa4 })] [InlineData(nameof(HashAlgorithmName.SHA512), 1024 / 8, new byte[] { 0xba, 0xf6, 0xed, 0xa7, 0x3a, 0xf7, 0x12, 0x27 })] [InlineData(nameof(HashAlgorithmName.SHA512), 1024 / 8 + 1, new byte[] { 0x34, 0xdf, 0x2d, 0x21, 0xfd, 0xf1, 0x0e, 0x13 })] +#if NET8_0_OR_GREATER + [InlineData("SHA3-256", 1088 / 8 - 1, new byte[] { 0xa1, 0x96, 0xae, 0x83, 0x56, 0xf4, 0x2a, 0x4b })] + [InlineData("SHA3-256", 1088 / 8, new byte[] { 0xe7, 0xe9, 0xe0, 0x98, 0x09, 0x54, 0x54, 0x2d })] + [InlineData("SHA3-256", 1088 / 8 + 1, new byte[] { 0x7d, 0x7a, 0x71, 0xdf, 0x1f, 0x5d, 0x5b, 0x44 })] + [InlineData("SHA3-384", 832 / 8 - 1, new byte[] { 0xd6, 0x08, 0x69, 0xd0, 0x99, 0x98, 0x6d, 0xcc })] + [InlineData("SHA3-384", 832 / 8, new byte[] { 0x49, 0x83, 0x06, 0x4e, 0x08, 0xf8, 0x93, 0x62 })] + [InlineData("SHA3-384", 832 / 8 + 1, new byte[] { 0xcc, 0x03, 0x1f, 0x57, 0x5e, 0x0c, 0xe1, 0xe8 })] + [InlineData("SHA3-512", 576 / 8 - 1, new byte[] { 0x47, 0xd2, 0x7e, 0x61, 0x01, 0x61, 0x9a, 0xd0 })] + [InlineData("SHA3-512", 576 / 8, new byte[] { 0xda, 0x56, 0x5b, 0x08, 0x73, 0xbc, 0x4d, 0x33 })] + [InlineData("SHA3-512", 576 / 8 + 1, new byte[] { 0xd3, 0xa1, 0xfd, 0x76, 0xc4, 0xf9, 0x62, 0xc3 })] +#endif public static void Kdk_HmacBlockBoundarySizes(string hashAlgorithmName, int kdkSize, byte[] expected) { +#if NET8_0_OR_GREATER + if ((hashAlgorithmName == "SHA3-256" && !SHA3_256.IsSupported) || + (hashAlgorithmName == "SHA3-384" && !SHA3_384.IsSupported) || + (hashAlgorithmName == "SHA3-512" && !SHA3_512.IsSupported)) + { + throw new SkipTestException($"Algorithm '{hashAlgorithmName}' is not supported on the current platform."); + } +#endif + // We do HMAC key adjust for the CNG implementation when the kdk exceeds the block size of the HMAC algorithm. // This tests one byte below, at, and above the block size for each HMAC algorithm. // Verified against OpenSSL 3. Example command used below. Adjust the digest and the seq upper boundary as needed. @@ -306,6 +327,149 @@ public static IEnumerable GetOutputLengthBoundaries() 0x61, } }; + +#if NET8_0_OR_GREATER + if (HMACSHA3_256.IsSupported) + { + // HMACSHA3_256 output size is 32 bytes + yield return new object[] + { + "SHA3-256", + new byte[63] + { + 0x25, 0xb6, 0xc5, 0xba, 0x60, 0x47, 0x95, 0xb6, 0x5c, 0x92, 0xcb, 0x8f, 0xd2, 0x4d, 0x40, 0xfa, + 0x68, 0xa9, 0xa6, 0xd3, 0x2c, 0x7f, 0x3c, 0xcd, 0x88, 0x89, 0xdc, 0x45, 0x10, 0xeb, 0x16, 0x38, + 0xf3, 0xe2, 0xe0, 0x26, 0xb5, 0xbc, 0x61, 0x9f, 0x56, 0x66, 0x7d, 0xbd, 0x55, 0x4e, 0x6b, 0x70, + 0x84, 0xc1, 0x9c, 0x95, 0x1e, 0x8f, 0x1b, 0xdc, 0xc2, 0x68, 0xc3, 0x10, 0x9c, 0x13, 0xf8, + } + }; + + yield return new object[] + { + "SHA3-256", + new byte[64] + { + 0xc8, 0x8a, 0xfe, 0xd4, 0x62, 0xa6, 0x9e, 0xa6, 0x90, 0xa7, 0xb1, 0xe2, 0x01, 0xff, 0x67, 0x52, + 0x5d, 0xca, 0xa9, 0x13, 0xa2, 0x92, 0x3c, 0xc0, 0x42, 0xd1, 0x1b, 0xe2, 0xff, 0xe0, 0xa2, 0xb9, + 0x48, 0x3d, 0xb1, 0x17, 0x73, 0x76, 0x3d, 0x37, 0x0f, 0xc6, 0x6f, 0x65, 0xa5, 0xb9, 0x23, 0xcf, + 0xc0, 0xd4, 0x5f, 0xdf, 0x46, 0x0e, 0xab, 0xce, 0x8e, 0x7d, 0x2c, 0x9d, 0x71, 0x40, 0xf0, 0x89, + } + }; + + yield return new object[] + { + "SHA3-256", + new byte[65] + { + 0xcc, 0x3a, 0x45, 0x55, 0x26, 0x1e, 0x56, 0xf4, 0x3c, 0x18, 0x66, 0x1d, 0xa8, 0xe3, 0x91, 0xe7, + 0xbc, 0xc3, 0x93, 0x1f, 0x85, 0xbe, 0x0c, 0xfb, 0xab, 0x10, 0xa1, 0x52, 0x93, 0xc7, 0x3c, 0xac, + 0x20, 0x09, 0xfb, 0x40, 0x95, 0xb9, 0x0f, 0x0a, 0x35, 0x50, 0xe2, 0x05, 0x33, 0x20, 0xdd, 0xb0, + 0xb7, 0xca, 0xda, 0x15, 0xa8, 0xc8, 0x73, 0x5d, 0xb7, 0x22, 0x5f, 0x23, 0xef, 0xcd, 0x33, 0x41, + 0xa2, + } + }; + } + + if (HMACSHA3_384.IsSupported) + { + // HMACSHA3_384 output size is 48 bytes + yield return new object[] + { + "SHA3-384", + new byte[95] + { + 0x80, 0x3b, 0x0a, 0x83, 0xe5, 0xae, 0xab, 0xff, 0x16, 0x7a, 0x04, 0x60, 0x97, 0x74, 0x39, 0xcf, + 0x8b, 0xeb, 0xbb, 0x57, 0x89, 0x62, 0x24, 0xab, 0x01, 0x61, 0xce, 0x23, 0xbc, 0xc1, 0xe0, 0xc4, + 0x9e, 0x73, 0xd1, 0x21, 0xdc, 0x21, 0xee, 0x30, 0xdb, 0xec, 0xb0, 0xbf, 0xec, 0xaa, 0x24, 0x18, + 0xf9, 0x93, 0xda, 0xd1, 0xaf, 0xfe, 0xbb, 0x1c, 0x7f, 0xcd, 0xea, 0x8f, 0x57, 0x41, 0x3c, 0x01, + 0xa8, 0x94, 0x06, 0x27, 0x8d, 0x95, 0x5d, 0x62, 0x61, 0xe7, 0x67, 0x60, 0xc4, 0xa2, 0xc4, 0xf5, + 0x7e, 0x38, 0x6e, 0x30, 0x38, 0x83, 0x7d, 0x5e, 0xf4, 0x0f, 0xdf, 0xd3, 0xac, 0x65, 0x48, + } + }; + + yield return new object[] + { + "SHA3-384", + new byte[96] + { + 0xb8, 0xea, 0xbd, 0xcb, 0x67, 0xcb, 0xd7, 0xf5, 0x12, 0xdf, 0xc2, 0x35, 0x89, 0x66, 0x80, 0x6f, + 0xc4, 0x7c, 0x28, 0xf2, 0x4b, 0xf5, 0xd1, 0x4d, 0x54, 0x4c, 0x78, 0xae, 0xde, 0xc2, 0xae, 0xb0, + 0x7d, 0xfc, 0x02, 0x6e, 0x0e, 0x08, 0x2b, 0xfc, 0xd2, 0x2b, 0xae, 0xfc, 0xa1, 0x55, 0xf7, 0xc7, + 0xd5, 0x77, 0xe4, 0x84, 0xbb, 0x53, 0x1d, 0x3d, 0xd2, 0x7a, 0x61, 0x97, 0x8a, 0xd3, 0xae, 0x1b, + 0x47, 0xbe, 0xa9, 0x40, 0x02, 0xac, 0x55, 0x1b, 0x74, 0x72, 0x02, 0x5b, 0xa8, 0xa8, 0xd4, 0xfe, + 0xcf, 0xd1, 0xb2, 0x44, 0x01, 0xec, 0xb7, 0xef, 0x63, 0x0f, 0x16, 0xae, 0xa9, 0x63, 0xb1, 0x56, + } + }; + + yield return new object[] + { + "SHA3-384", + new byte[97] + { + 0x62, 0x93, 0xa5, 0x45, 0x03, 0x7a, 0x2f, 0x50, 0xfe, 0x6b, 0xe6, 0x85, 0x56, 0x88, 0x8c, 0x78, + 0xbd, 0x4f, 0x08, 0x68, 0xdd, 0x33, 0xab, 0x18, 0x05, 0x81, 0x79, 0x70, 0x24, 0xe0, 0x3f, 0x94, + 0x40, 0x9b, 0xc3, 0x41, 0xa2, 0xe0, 0xfd, 0x02, 0xe8, 0xb8, 0x41, 0x53, 0x2e, 0x95, 0x59, 0xc5, + 0xf7, 0xab, 0x5b, 0xe9, 0x2d, 0x15, 0x0a, 0xcc, 0xb8, 0xc0, 0x87, 0xbd, 0x78, 0x39, 0xb9, 0xb8, + 0x83, 0x2c, 0x49, 0x7b, 0x45, 0x9b, 0x81, 0xed, 0x33, 0xdc, 0x75, 0xf1, 0x7d, 0xbd, 0x44, 0xce, + 0xa5, 0xf3, 0xbe, 0x43, 0xa5, 0x15, 0x7c, 0x7e, 0xcd, 0x06, 0x09, 0xb0, 0x4a, 0x17, 0x48, 0xf3, + 0x51, + } + }; + } + + if (HMACSHA3_512.IsSupported) + { + // HMACSHA3_512 output size is 64 bytes + yield return new object[] + { + "SHA3-512", + new byte[127] + { + 0x41, 0xe4, 0xb5, 0xe6, 0x5b, 0x8c, 0xce, 0x14, 0xa8, 0x39, 0xd3, 0xdf, 0xb4, 0x27, 0x0f, 0xff, + 0x1f, 0x9a, 0xca, 0x24, 0x03, 0x59, 0x4b, 0x86, 0x40, 0x66, 0xf0, 0xae, 0xdc, 0x59, 0x44, 0x0e, + 0x6a, 0x87, 0xa5, 0x38, 0x5a, 0x79, 0x27, 0xa5, 0x61, 0x91, 0x1a, 0x9d, 0x39, 0xca, 0x80, 0xe0, + 0x11, 0x3b, 0xd0, 0xfa, 0x2e, 0x48, 0x70, 0x83, 0x31, 0xa7, 0xa6, 0x6c, 0x5f, 0xf2, 0x2f, 0x09, + 0x5b, 0x1e, 0xad, 0x8b, 0x4f, 0xbd, 0x63, 0x26, 0x6f, 0xcd, 0xc6, 0xce, 0xff, 0xa6, 0x86, 0xbe, + 0xf6, 0x4b, 0x81, 0x63, 0x65, 0x24, 0x48, 0xbc, 0x59, 0x6a, 0x4f, 0x00, 0xb5, 0x9e, 0x9b, 0xbd, + 0x85, 0xbc, 0xf6, 0xf1, 0xf1, 0xaa, 0xd3, 0x91, 0x9b, 0x7b, 0x26, 0xfe, 0xd0, 0xd7, 0x4c, 0x34, + 0xdd, 0x2c, 0x57, 0x2e, 0x10, 0x09, 0x76, 0x32, 0xed, 0x3a, 0x95, 0x7d, 0x88, 0x2b, 0xdc, + } + }; + + yield return new object[] + { + "SHA3-512", + new byte[128] + { + 0xbe, 0x9f, 0x29, 0xd7, 0x9d, 0x11, 0x7e, 0xd7, 0x33, 0xd4, 0xcf, 0x66, 0xed, 0x1a, 0x61, 0xfd, + 0xb0, 0x68, 0x3b, 0x03, 0xd1, 0x7c, 0x1a, 0x69, 0xd0, 0x33, 0x1c, 0xf4, 0x7a, 0xf0, 0x4a, 0x46, + 0xed, 0x4a, 0x33, 0xbf, 0x2b, 0x18, 0x16, 0x4b, 0xda, 0x30, 0x96, 0x11, 0xee, 0x52, 0x4b, 0x0e, + 0x22, 0xa0, 0x8f, 0xb0, 0xdc, 0xe6, 0x8c, 0x57, 0xd0, 0x6e, 0x25, 0xd8, 0x29, 0xf7, 0xf9, 0x94, + 0xe3, 0x73, 0x20, 0x4e, 0x11, 0xc0, 0xa9, 0x3b, 0x00, 0xf0, 0x8e, 0xff, 0xb3, 0x07, 0x87, 0x4c, + 0x3b, 0x96, 0x09, 0xff, 0x14, 0x3b, 0x65, 0x17, 0x5f, 0x54, 0x16, 0xaf, 0x15, 0xe5, 0x59, 0x5b, + 0x75, 0xf5, 0x03, 0x61, 0x5b, 0xd9, 0xf3, 0x7c, 0x71, 0x96, 0xaa, 0x67, 0xef, 0xdd, 0x40, 0x4c, + 0xd2, 0x9e, 0xf6, 0x05, 0x02, 0x93, 0x23, 0x83, 0x33, 0xcc, 0x0f, 0xf2, 0xdd, 0x9c, 0xd6, 0x46, + } + }; + + yield return new object[] + { + "SHA3-512", + new byte[129] + { + 0x5f, 0xf7, 0xd9, 0x1e, 0x98, 0xb3, 0xa4, 0xab, 0x4d, 0xc8, 0x50, 0x9a, 0xd7, 0x50, 0x37, 0xba, + 0x10, 0xeb, 0x1b, 0x10, 0x5f, 0x6c, 0xfe, 0x81, 0x75, 0x5d, 0x6c, 0x63, 0x8a, 0xfe, 0x60, 0x4f, + 0xb3, 0x9e, 0xf4, 0x84, 0x5d, 0xa3, 0x88, 0xf7, 0x29, 0x5c, 0x30, 0xbb, 0xf7, 0x30, 0x69, 0x84, + 0xab, 0x9e, 0xc6, 0xb0, 0xc3, 0xce, 0x45, 0x7a, 0xf2, 0xac, 0x18, 0x0b, 0x09, 0x8c, 0xbb, 0xae, + 0x22, 0x12, 0xef, 0xd8, 0xec, 0x6f, 0x9f, 0xbf, 0x09, 0x7f, 0xe2, 0xb6, 0xc8, 0x6a, 0xf7, 0x5e, + 0x86, 0x27, 0x22, 0xeb, 0xa8, 0x7b, 0x1f, 0x54, 0x97, 0x16, 0x0f, 0x21, 0xad, 0xcd, 0xd9, 0x9d, + 0xd6, 0x01, 0x0b, 0x79, 0xe9, 0x16, 0xd8, 0xcd, 0xa6, 0x93, 0x25, 0xd1, 0xeb, 0xac, 0x9b, 0x5f, + 0x26, 0xf4, 0xad, 0x0a, 0xf2, 0xc6, 0x4d, 0xad, 0x69, 0x96, 0xb7, 0xc8, 0xcd, 0xe0, 0x13, 0xfb, + 0xf6, + } + }; + } +#endif } public static IEnumerable GetRfc8009TestVectors() diff --git a/src/libraries/Common/tests/System/TimeProviderTests.cs b/src/libraries/Common/tests/System/TimeProviderTests.cs index b3fe700165e2fd..93a92dde712907 100644 --- a/src/libraries/Common/tests/System/TimeProviderTests.cs +++ b/src/libraries/Common/tests/System/TimeProviderTests.cs @@ -321,7 +321,7 @@ public static void RunDelayTests(TimeProvider provider, ITestTaskFactory taskFac [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [MemberData(nameof(TimersProvidersWithTaskFactorData))] - public static async void RunWaitAsyncTests(TimeProvider provider, ITestTaskFactory taskFactory) + public static async Task RunWaitAsyncTests(TimeProvider provider, ITestTaskFactory taskFactory) { CancellationTokenSource cts = new CancellationTokenSource(); @@ -377,7 +377,7 @@ public static async void RunWaitAsyncTests(TimeProvider provider, ITestTaskFacto #if !NETFRAMEWORK [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] [MemberData(nameof(TimersProvidersListData))] - public static async void PeriodicTimerTests(TimeProvider provider) + public static async Task PeriodicTimerTests(TimeProvider provider) { var timer = new PeriodicTimer(TimeSpan.FromMilliseconds(1), provider); Assert.True(await timer.WaitForNextTickAsync()); diff --git a/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs b/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs index 479d2aef83c6e2..bf676b7b6f26be 100644 --- a/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs +++ b/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs @@ -405,6 +405,15 @@ public static void Equal(HashSet expected, HashSet actual) } } + /// Validates that the two sets contains the same elements. XUnit doesn't display the full collections. + public static void Equal(ISet expected, ISet actual) + { + if (!actual.SetEquals(expected)) + { + throw new XunitException($"Expected: {string.Join(", ", expected)}{Environment.NewLine}Actual: {string.Join(", ", actual)}"); + } + } + /// /// Validates that the actual collection contains same items as expected collection. If the test fails, this will display: /// 1. Count if two collection count are different; diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index 68ca7995303e7e..88ab461e49dcea 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -303,6 +303,7 @@ private static bool GetAlpnSupport() private static readonly Lazy s_supportsTls12 = new Lazy(GetTls12Support); private static readonly Lazy s_supportsTls13 = new Lazy(GetTls13Support); private static readonly Lazy s_sendsCAListByDefault = new Lazy(GetSendsCAListByDefault); + private static readonly Lazy s_supportsSha3 = new Lazy(GetSupportsSha3); public static bool SupportsTls10 => s_supportsTls10.Value; public static bool SupportsTls11 => s_supportsTls11.Value; @@ -310,6 +311,8 @@ private static bool GetAlpnSupport() public static bool SupportsTls13 => s_supportsTls13.Value; public static bool SendsCAListByDefault => s_sendsCAListByDefault.Value; public static bool SupportsSendingCustomCANamesInTls => UsesAppleCrypto || IsOpenSslSupported || (PlatformDetection.IsWindows8xOrLater && SendsCAListByDefault); + public static bool SupportsSha3 => s_supportsSha3.Value; + public static bool DoesNotSupportSha3 => !s_supportsSha3.Value; private static readonly Lazy s_largeArrayIsNotSupported = new Lazy(IsLargeArrayNotSupported); @@ -651,5 +654,25 @@ private static bool AssemblyConfigurationEquals(string configuration) return assemblyConfigurationAttribute != null && string.Equals(assemblyConfigurationAttribute.Configuration, configuration, StringComparison.InvariantCulture); } + + private static bool GetSupportsSha3() + { + if (IsOpenSslSupported) + { + if (OpenSslVersion.Major >= 3) + { + return true; + } + + return OpenSslVersion.Major == 1 && OpenSslVersion.Minor >= 1 && OpenSslVersion.Build >= 1; + } + + if (IsWindowsVersionOrLater(10, 0, 25324)) + { + return true; + } + + return false; + } } } diff --git a/src/libraries/Directory.Build.targets b/src/libraries/Directory.Build.targets index bc1e24d670a421..8e000b5f4d7604 100644 --- a/src/libraries/Directory.Build.targets +++ b/src/libraries/Directory.Build.targets @@ -47,14 +47,8 @@ --> $(WarningsAsErrors.Replace('NU1605', '')) - true - - true true - true + true true diff --git a/src/libraries/Microsoft.Bcl.Cryptography/src/System/Security/Cryptography/HashAlgorithmNames.cs b/src/libraries/Microsoft.Bcl.Cryptography/src/System/Security/Cryptography/HashAlgorithmNames.cs index 8f10590302e4bb..feb43d2caa487b 100644 --- a/src/libraries/Microsoft.Bcl.Cryptography/src/System/Security/Cryptography/HashAlgorithmNames.cs +++ b/src/libraries/Microsoft.Bcl.Cryptography/src/System/Security/Cryptography/HashAlgorithmNames.cs @@ -3,11 +3,15 @@ namespace System.Security.Cryptography { + // Strings need to match CNG identifiers. internal static class HashAlgorithmNames { internal const string SHA1 = nameof(SHA1); internal const string SHA256 = nameof(SHA256); internal const string SHA384 = nameof(SHA384); internal const string SHA512 = nameof(SHA512); + internal const string SHA3_256 = "SHA3-256"; + internal const string SHA3_384 = "SHA3-384"; + internal const string SHA3_512 = "SHA3-512"; } } diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/IDispatchMetaObject.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/IDispatchMetaObject.cs index d1c80b62c0a580..c6aed3cca13b6e 100644 --- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/IDispatchMetaObject.cs +++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/IDispatchMetaObject.cs @@ -11,6 +11,7 @@ namespace Microsoft.CSharp.RuntimeBinder.ComInterop internal sealed class IDispatchMetaObject : ComFallbackMetaObject { private readonly IDispatchComObject _self; + private static readonly bool[] s_false = new bool[] { false }; [RequiresUnreferencedCode(Binder.TrimmerWarning)] internal IDispatchMetaObject(Expression expression, IDispatchComObject self) @@ -218,7 +219,7 @@ private DynamicMetaObject TryPropertyPut(SetMemberBinder binder, DynamicMetaObje DynamicMetaObject result = new ComInvokeBinder( new CallInfo(1), new[] { value }, - new bool[] { false }, + s_false, restrictions, Expression.Constant(method), dispatch, diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantArray.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantArray.cs index 71e466deb0acf0..37e34303feadff 100644 --- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantArray.cs +++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/ComInterop/VariantArray.cs @@ -49,6 +49,7 @@ internal static class VariantArray // Don't need a dictionary for this, it will have very few elements // (guaranteed less than 28, in practice 0-2) private static readonly List s_generatedTypes = new List(0); + private static readonly string[] s_genericTName = new string[] { "T" }; [DynamicDependency(DynamicallyAccessedMemberTypes.PublicFields, typeof(VariantArray1))] [DynamicDependency(DynamicallyAccessedMemberTypes.PublicFields, typeof(VariantArray2))] @@ -100,7 +101,7 @@ private static Type CreateCustomType(int size) { TypeAttributes attrs = TypeAttributes.NotPublic | TypeAttributes.SequentialLayout; TypeBuilder type = UnsafeMethods.DynamicModule.DefineType("VariantArray" + size, attrs, typeof(ValueType)); - GenericTypeParameterBuilder T = type.DefineGenericParameters(new string[] { "T" })[0]; + GenericTypeParameterBuilder T = type.DefineGenericParameters(s_genericTName)[0]; for (int i = 0; i < size; i++) { type.DefineField("Element" + i, T, FieldAttributes.Public); diff --git a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs index 8deb86a491c978..f2d34b30cb9a79 100644 --- a/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs +++ b/src/libraries/Microsoft.CSharp/src/Microsoft/CSharp/RuntimeBinder/Semantics/ExpressionBinder.cs @@ -1151,7 +1151,7 @@ private void AdjustCallArgumentsForParams(CType callingObjectType, CType type, M CType arrayType = (ArrayType)TypeManager.SubstType(mp.Params[mp.Params.Count - 1], type, pTypeArgs); // Use an EK_ARRINIT even in the empty case so empty param arrays in attributes work. - ExprArrayInit arrayInit = ExprFactory.CreateArrayInit(arrayType, null, null, new[] { 0 }); + ExprArrayInit arrayInit = ExprFactory.CreateArrayInit(arrayType, null, null, s_zero); arrayInit.GeneratedForParamArray = true; arrayInit.OptionalArguments = named.Value; @@ -1229,7 +1229,7 @@ private void AdjustCallArgumentsForParams(CType callingObjectType, CType type, M CType elementType = subArr.ElementType; // Use an EK_ARRINIT even in the empty case so empty param arrays in attributes work. - ExprArrayInit exprArrayInit = ExprFactory.CreateArrayInit(substitutedArrayType, null, null, new[] { 0 }); + ExprArrayInit exprArrayInit = ExprFactory.CreateArrayInit(substitutedArrayType, null, null, s_zero); exprArrayInit.GeneratedForParamArray = true; if (it.AtEnd()) @@ -1618,6 +1618,8 @@ private static void CheckUnsafe(CType type) private AggregateSymbol ContextForMemberLookup => Context.ContextForMemberLookup; + private static readonly int[] s_zero = new[] { 0 }; + private static ExprWrap WrapShortLivedExpression(Expr expr) => ExprFactory.CreateWrap(expr); private static ExprAssignment GenerateOptimizedAssignment(Expr op1, Expr op2) => ExprFactory.CreateAssignment(op1, op2); 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 f309f203486bf7..911a00d91fdbd5 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Emitter.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Emitter.cs @@ -176,7 +176,7 @@ private void EmitGetValueMethods() if (_generationSpec.ShouldEmitMethods(BinderMethodSpecifier.GetValue_TypeOf_key_defaultValue)) { EmitBlankLineIfRequired(); - _writer.WriteLine($"public static object? {Identifier.GetValue}(this {FullyQualifiedDisplayName.IConfiguration} {Identifier.configuration}, {FullyQualifiedDisplayName.Type} {Identifier.type}, string {Identifier.key}, object? {Identifier.defaultValue}) =>" + + _writer.WriteLine($"public static object? {Identifier.GetValue}(this {FullyQualifiedDisplayName.IConfiguration} {Identifier.configuration}, {FullyQualifiedDisplayName.Type} {Identifier.type}, string {Identifier.key}, object? {Identifier.defaultValue}) => " + $"{expressionForGetValueCore}({Identifier.configuration}, {Identifier.type}, {Identifier.key}) ?? {Identifier.defaultValue};"); } } @@ -527,7 +527,7 @@ private void EmitHelperMethods() _precedingBlockExists = true; } - if (_generationSpec.ShouldEmitMethods(BinderMethodSpecifier.RootMethodsWithConfigOptions)) + if (_generationSpec.ShouldEmitMethods(BinderMethodSpecifier.MethodsThatAssessBinderOptions)) { _writer.WriteBlankLine(); EmitGetBinderOptionsHelper(); 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 020c1104018669..4064232c5a7153 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.Parser.cs @@ -7,7 +7,6 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; -using System.Runtime.CompilerServices; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Operations; @@ -15,7 +14,7 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration { public sealed partial class ConfigurationBindingGenerator { - private sealed class Parser + private sealed partial class Parser { private readonly SourceProductionContext _context; private readonly KnownTypeSymbols _typeSymbols; @@ -140,18 +139,19 @@ private void ProcessBindCall(BinderInvocationOperation binderOperation) } ITypeSymbol? type = ResolveType(objectArg.Value)?.WithNullableAnnotation(NullableAnnotation.None); - INamedTypeSymbol? namedType; - if ((namedType = type as INamedTypeSymbol) is null || - namedType.SpecialType == SpecialType.System_Object || - namedType.SpecialType == SpecialType.System_Void || - // Binding to root-level struct is a no-op. - namedType.IsValueType) + if (!IsValidRootConfigType(overload, type, binderOperation.Location)) { return; } - AddRootConfigType(methodGroup: BinderMethodSpecifier.Bind, overload, namedType, binderOperation.Location); + if (type.IsValueType) + { + _context.ReportDiagnostic(Diagnostic.Create(Diagnostics.ValueTypesInvalidForBind, binderOperation.Location, type)); + return; + } + + AddRootConfigType(methodGroup: BinderMethodSpecifier.Bind, overload, type, binderOperation.Location); static ITypeSymbol? ResolveType(IOperation conversionOperation) => conversionOperation switch @@ -180,7 +180,7 @@ private void ProcessGetCall(BinderInvocationOperation binderOperation) } BinderMethodSpecifier overload = BinderMethodSpecifier.None; - INamedTypeSymbol? namedType; + ITypeSymbol? type; if (targetMethod.IsGenericMethod) { @@ -189,7 +189,7 @@ private void ProcessGetCall(BinderInvocationOperation binderOperation) return; } - namedType = targetMethod.TypeArguments[0].WithNullableAnnotation(NullableAnnotation.None) as INamedTypeSymbol; + type = targetMethod.TypeArguments[0].WithNullableAnnotation(NullableAnnotation.None); if (paramLength is 1) { @@ -207,7 +207,7 @@ private void ProcessGetCall(BinderInvocationOperation binderOperation) else { ITypeOfOperation? typeOfOperation = operation.Arguments[1].ChildOperations.FirstOrDefault() as ITypeOfOperation; - namedType = typeOfOperation?.TypeOperand as INamedTypeSymbol; + type = typeOfOperation?.TypeOperand; if (paramLength is 2) { @@ -219,15 +219,12 @@ private void ProcessGetCall(BinderInvocationOperation binderOperation) } } - if (overload is BinderMethodSpecifier.None || - namedType is null || - namedType.SpecialType == SpecialType.System_Object || - namedType.SpecialType == SpecialType.System_Void) + if (!IsValidRootConfigType(overload, type, binderOperation.Location)) { return; } - AddRootConfigType(methodGroup: BinderMethodSpecifier.Get, overload, namedType, binderOperation.Location); + AddRootConfigType(methodGroup: BinderMethodSpecifier.Get, overload, type, binderOperation.Location); } private void ProcessGetValueCall(BinderInvocationOperation binderOperation) @@ -282,15 +279,12 @@ private void ProcessGetValueCall(BinderInvocationOperation binderOperation) } } - if (overload is BinderMethodSpecifier.None || - type is null || - type.SpecialType == SpecialType.System_Object || - type.SpecialType == SpecialType.System_Void) + if (!IsValidRootConfigType(overload, type, binderOperation.Location)) { return; } - ITypeSymbol effectiveType = IsNullable(type, out ITypeSymbol? underlyingType) ? underlyingType : type; + ITypeSymbol effectiveType = (IsNullable(type, out ITypeSymbol? underlyingType) ? underlyingType : type)!; if (IsParsableFromString(effectiveType, out _)) { AddRootConfigType(methodGroup: BinderMethodSpecifier.GetValue, overload, type, binderOperation.Location); @@ -310,23 +304,38 @@ private void ProcessConfigureCall(BinderInvocationOperation binderOperation) SymbolEqualityComparer.Default.Equals(_typeSymbols.IConfiguration, @params[1].Type)) { ITypeSymbol? type = targetMethod.TypeArguments[0].WithNullableAnnotation(NullableAnnotation.None); - if (type is not INamedTypeSymbol namedType || - namedType.SpecialType == SpecialType.System_Object) + + if (!IsValidRootConfigType(BinderMethodSpecifier.Configure, type, binderOperation.Location)) { return; } - AddRootConfigType(methodGroup: BinderMethodSpecifier.Configure, overload: BinderMethodSpecifier.Configure, namedType, binderOperation.Location); + AddRootConfigType(methodGroup: BinderMethodSpecifier.Configure, overload: BinderMethodSpecifier.Configure, type, binderOperation.Location); } } - private void AddRootConfigType(BinderMethodSpecifier methodGroup, BinderMethodSpecifier overload, ITypeSymbol type, Location? location) + private bool IsValidRootConfigType(BinderMethodSpecifier overload, ITypeSymbol? type, Location? location) { - if (type is INamedTypeSymbol namedType && ContainsGenericParameters(namedType)) + if (overload is BinderMethodSpecifier.None) { - return; + return false; + } + + if (type is null || + type.SpecialType is SpecialType.System_Object or SpecialType.System_Void || + type.TypeKind is TypeKind.TypeParameter or TypeKind.Pointer or TypeKind.Error || + type.IsRefLikeType || + ContainsGenericParameters(type)) + { + _context.ReportDiagnostic(Diagnostic.Create(Diagnostics.CouldNotDetermineTypeInfo, location)); + return false; } + return true; + } + + private void AddRootConfigType(BinderMethodSpecifier methodGroup, BinderMethodSpecifier overload, ITypeSymbol type, Location? location) + { if (GetOrCreateTypeSpec(type, location) is TypeSpec spec) { RegisterConfigType(spec, overload); @@ -345,7 +354,7 @@ private void AddRootConfigType(BinderMethodSpecifier methodGroup, BinderMethodSp if (IsNullable(type, out ITypeSymbol? underlyingType)) { - spec = TryGetTypeSpec(underlyingType, ParserDiagnostics.NullableUnderlyingTypeNotSupported, out TypeSpec? underlyingTypeSpec) + spec = TryGetTypeSpec(underlyingType, Diagnostics.NullableUnderlyingTypeNotSupported, out TypeSpec? underlyingTypeSpec) ? new NullableSpec(type) { Location = location, UnderlyingType = underlyingTypeSpec } : null; } @@ -386,7 +395,7 @@ private void AddRootConfigType(BinderMethodSpecifier methodGroup, BinderMethodSp if (spec is null) { - ReportUnsupportedType(type, ParserDiagnostics.TypeNotSupported, location); + ReportUnsupportedType(type, Diagnostics.TypeNotSupported, location); return null; } @@ -562,7 +571,7 @@ private bool TryGetTypeSpec(ITypeSymbol type, DiagnosticDescriptor descriptor, o private EnumerableSpec? CreateArraySpec(IArrayTypeSymbol arrayType, Location? location) { - if (!TryGetTypeSpec(arrayType.ElementType, ParserDiagnostics.ElementTypeNotSupported, out TypeSpec elementSpec)) + if (!TryGetTypeSpec(arrayType.ElementType, Diagnostics.ElementTypeNotSupported, out TypeSpec elementSpec)) { return null; } @@ -594,7 +603,7 @@ private bool IsSupportedArrayType(ITypeSymbol type, Location? location) if (arrayType.Rank > 1) { - ReportUnsupportedType(arrayType, ParserDiagnostics.MultiDimArraysNotSupported, location); + ReportUnsupportedType(arrayType, Diagnostics.MultiDimArraysNotSupported, location); return false; } @@ -624,15 +633,15 @@ private bool IsSupportedArrayType(ITypeSymbol type, Location? location) private DictionarySpec CreateDictionarySpec(INamedTypeSymbol type, Location? location, ITypeSymbol keyType, ITypeSymbol elementType) { - if (!TryGetTypeSpec(keyType, ParserDiagnostics.DictionaryKeyNotSupported, out TypeSpec keySpec) || - !TryGetTypeSpec(elementType, ParserDiagnostics.ElementTypeNotSupported, out TypeSpec elementSpec)) + if (!TryGetTypeSpec(keyType, Diagnostics.DictionaryKeyNotSupported, out TypeSpec keySpec) || + !TryGetTypeSpec(elementType, Diagnostics.ElementTypeNotSupported, out TypeSpec elementSpec)) { return null; } if (keySpec.SpecKind != TypeSpecKind.ParsableFromString) { - ReportUnsupportedType(type, ParserDiagnostics.DictionaryKeyNotSupported, location); + ReportUnsupportedType(type, Diagnostics.DictionaryKeyNotSupported, location); return null; } @@ -657,7 +666,7 @@ private DictionarySpec CreateDictionarySpec(INamedTypeSymbol type, Location? loc } else { - ReportUnsupportedType(type, ParserDiagnostics.CollectionNotSupported, location); + ReportUnsupportedType(type, Diagnostics.CollectionNotSupported, location); return null; } } @@ -678,7 +687,7 @@ private DictionarySpec CreateDictionarySpec(INamedTypeSymbol type, Location? loc } else { - ReportUnsupportedType(type, ParserDiagnostics.CollectionNotSupported, location); + ReportUnsupportedType(type, Diagnostics.CollectionNotSupported, location); return null; } @@ -702,7 +711,7 @@ private DictionarySpec CreateDictionarySpec(INamedTypeSymbol type, Location? loc private EnumerableSpec? CreateEnumerableSpec(INamedTypeSymbol type, Location? location) { if (!TryGetElementType(type, out ITypeSymbol? elementType) || - !TryGetTypeSpec(elementType, ParserDiagnostics.ElementTypeNotSupported, out TypeSpec elementSpec)) + !TryGetTypeSpec(elementType, Diagnostics.ElementTypeNotSupported, out TypeSpec elementSpec)) { return null; } @@ -727,7 +736,7 @@ private DictionarySpec CreateDictionarySpec(INamedTypeSymbol type, Location? loc } else { - ReportUnsupportedType(type, ParserDiagnostics.CollectionNotSupported, location); + ReportUnsupportedType(type, Diagnostics.CollectionNotSupported, location); return null; } } @@ -767,7 +776,7 @@ private DictionarySpec CreateDictionarySpec(INamedTypeSymbol type, Location? loc } else { - ReportUnsupportedType(type, ParserDiagnostics.CollectionNotSupported, location); + ReportUnsupportedType(type, Diagnostics.CollectionNotSupported, location); return null; } @@ -829,8 +838,8 @@ private DictionarySpec CreateDictionarySpec(INamedTypeSymbol type, Location? loc bool hasPublicParameterlessCtor = type.IsValueType || parameterlessCtor is not null; if (!hasPublicParameterlessCtor && hasMultipleParameterizedCtors) { - diagnosticDescriptor = ParserDiagnostics.MultipleParameterizedConstructors; - objectSpec.InitExceptionMessage = string.Format(ExceptionMessages.MultipleParameterizedConstructors, typeName); + diagnosticDescriptor = Diagnostics.MultipleParameterizedConstructors; + objectSpec.InitExceptionMessage = string.Format(Emitter.ExceptionMessages.MultipleParameterizedConstructors, typeName); } ctor = type.IsValueType @@ -843,8 +852,8 @@ private DictionarySpec CreateDictionarySpec(INamedTypeSymbol type, Location? loc if (ctor is null) { - diagnosticDescriptor = ParserDiagnostics.MissingPublicInstanceConstructor; - objectSpec.InitExceptionMessage = string.Format(ExceptionMessages.MissingPublicInstanceConstructor, typeName); + diagnosticDescriptor = Diagnostics.MissingPublicInstanceConstructor; + objectSpec.InitExceptionMessage = string.Format(Emitter.ExceptionMessages.MissingPublicInstanceConstructor, typeName); } if (diagnosticDescriptor is not null) @@ -869,7 +878,7 @@ private DictionarySpec CreateDictionarySpec(INamedTypeSymbol type, Location? loc TypeSpec? propertyTypeSpec = GetOrCreateTypeSpec(property.Type); if (propertyTypeSpec is null) { - _context.ReportDiagnostic(Diagnostic.Create(ParserDiagnostics.PropertyNotSupported, location, new string[] { propertyName, type.ToDisplayString() })); + _context.ReportDiagnostic(Diagnostic.Create(Diagnostics.PropertyNotSupported, location, new string[] { propertyName, type.ToDisplayString() })); } else { @@ -914,7 +923,7 @@ private DictionarySpec CreateDictionarySpec(INamedTypeSymbol type, Location? loc if (invalidParameters.Count > 0) { - objectSpec.InitExceptionMessage = string.Format(ExceptionMessages.CannotBindToConstructorParameter, typeName, FormatParams(invalidParameters)); + objectSpec.InitExceptionMessage = string.Format(Emitter.ExceptionMessages.CannotBindToConstructorParameter, typeName, FormatParams(invalidParameters)); } else if (missingParameters.Count > 0) { @@ -924,7 +933,7 @@ private DictionarySpec CreateDictionarySpec(INamedTypeSymbol type, Location? loc } else { - objectSpec.InitExceptionMessage = string.Format(ExceptionMessages.ConstructorParametersDoNotMatchProperties, typeName, FormatParams(missingParameters)); + objectSpec.InitExceptionMessage = string.Format(Emitter.ExceptionMessages.ConstructorParametersDoNotMatchProperties, typeName, FormatParams(missingParameters)); } } @@ -1021,16 +1030,17 @@ private static bool IsInterfaceMatch(INamedTypeSymbol type, INamedTypeSymbol @in return SymbolEqualityComparer.Default.Equals(type, @interface); } - public static bool ContainsGenericParameters(INamedTypeSymbol type) + public static bool ContainsGenericParameters(ITypeSymbol type) { - if (!type.IsGenericType) + if (type is not INamedTypeSymbol { IsGenericType: true } genericType) { return false; } - foreach (ITypeSymbol typeArg in type.TypeArguments) + foreach (ITypeSymbol typeArg in genericType.TypeArguments) { - if (typeArg.TypeKind == TypeKind.TypeParameter) + if (typeArg.TypeKind is TypeKind.TypeParameter or TypeKind.Error || + ContainsGenericParameters(typeArg)) { return true; } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.cs index 37b228343d7a63..cc0787ebf56d4e 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/ConfigurationBindingGenerator.cs @@ -54,7 +54,7 @@ private static void Execute(CompilationData compilationData, ImmutableArray + new DiagnosticDescriptor( + id: "SYSLIB1100", + title: new LocalizableResourceString(nameof(SR.TypeNotSupportedTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Configuration.Binder.SourceGeneration.SR)), + messageFormat: new LocalizableResourceString(nameofLocalizableMessageFormat, SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Configuration.Binder.SourceGeneration.SR)), + category: ProjectName, + defaultSeverity: DiagnosticSeverity.Warning, + isEnabledByDefault: true); + } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/ParserDiagnostics.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/ParserDiagnostics.cs deleted file mode 100644 index be2631422fe391..00000000000000 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/ParserDiagnostics.cs +++ /dev/null @@ -1,45 +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 Microsoft.CodeAnalysis; - -namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration -{ - internal static class ParserDiagnostics - { - public static DiagnosticDescriptor TypeNotSupported { get; } = CreateTypeNotSupportedDescriptor(nameof(SR.TypeNotSupported)); - public static DiagnosticDescriptor MissingPublicInstanceConstructor { get; } = CreateTypeNotSupportedDescriptor(nameof(SR.MissingPublicInstanceConstructor)); - public static DiagnosticDescriptor CollectionNotSupported { get; } = CreateTypeNotSupportedDescriptor(nameof(SR.CollectionNotSupported)); - public static DiagnosticDescriptor DictionaryKeyNotSupported { get; } = CreateTypeNotSupportedDescriptor(nameof(SR.DictionaryKeyNotSupported)); - public static DiagnosticDescriptor ElementTypeNotSupported { get; } = CreateTypeNotSupportedDescriptor(nameof(SR.ElementTypeNotSupported)); - public static DiagnosticDescriptor MultipleParameterizedConstructors { get; } = CreateTypeNotSupportedDescriptor(nameof(SR.MultipleParameterizedConstructors)); - public static DiagnosticDescriptor MultiDimArraysNotSupported { get; } = CreateTypeNotSupportedDescriptor(nameof(SR.MultiDimArraysNotSupported)); - public static DiagnosticDescriptor NullableUnderlyingTypeNotSupported { get; } = CreateTypeNotSupportedDescriptor(nameof(SR.NullableUnderlyingTypeNotSupported)); - - public static DiagnosticDescriptor PropertyNotSupported { get; } = new DiagnosticDescriptor( - id: "SYSLIB1101", - title: new LocalizableResourceString(nameof(SR.PropertyNotSupportedTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Configuration.Binder.SourceGeneration.SR)), - messageFormat: new LocalizableResourceString(nameof(SR.PropertyNotSupportedMessageFormat), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Configuration.Binder.SourceGeneration.SR)), - category: ConfigurationBindingGenerator.ProjectName, - defaultSeverity: DiagnosticSeverity.Warning, - isEnabledByDefault: true); - - public static DiagnosticDescriptor LanguageVersionNotSupported { get; } = new DiagnosticDescriptor( - id: "SYSLIB1102", - title: new LocalizableResourceString(nameof(SR.LanguageVersionIsNotSupportedTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Configuration.Binder.SourceGeneration.SR)), - messageFormat: new LocalizableResourceString(nameof(SR.Language_VersionIsNotSupportedMessageFormat), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Configuration.Binder.SourceGeneration.SR)), - category: ConfigurationBindingGenerator.ProjectName, - defaultSeverity: DiagnosticSeverity.Error, - isEnabledByDefault: true); - - private static DiagnosticDescriptor CreateTypeNotSupportedDescriptor(string nameofLocalizableMessageFormat) => - new DiagnosticDescriptor( - id: "SYSLIB1100", - title: new LocalizableResourceString(nameof(SR.TypeNotSupportedTitle), SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Configuration.Binder.SourceGeneration.SR)), - messageFormat: new LocalizableResourceString(nameofLocalizableMessageFormat, SR.ResourceManager, typeof(FxResources.Microsoft.Extensions.Configuration.Binder.SourceGeneration.SR)), - category: ConfigurationBindingGenerator.ProjectName, - defaultSeverity: DiagnosticSeverity.Warning, - isEnabledByDefault: true); - } -} diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Microsoft.Extensions.Configuration.Binder.SourceGeneration.csproj b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Microsoft.Extensions.Configuration.Binder.SourceGeneration.csproj index c3929ec6ba6662..65150ea38a4111 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Microsoft.Extensions.Configuration.Binder.SourceGeneration.csproj +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Microsoft.Extensions.Configuration.Binder.SourceGeneration.csproj @@ -24,16 +24,16 @@ + - - - + + diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/BinderMethodSpecifier.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/BinderMethodSpecifier.cs index 33b2859a867bfa..dafbd0bee3c019 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/BinderMethodSpecifier.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/BinderMethodSpecifier.cs @@ -80,6 +80,7 @@ internal enum BinderMethodSpecifier Bind = Bind_instance | Bind_instance_BinderOptions | Bind_key_instance, Get = Get_T | Get_T_BinderOptions | Get_TypeOf | Get_TypeOf_BinderOptions, GetValue = GetValue_T_key | GetValue_T_key_defaultValue | GetValue_TypeOf_key | GetValue_TypeOf_key_defaultValue, - RootMethodsWithConfigOptions = Bind_instance_BinderOptions | Get_T_BinderOptions | Get_TypeOf_BinderOptions, + + MethodsThatAssessBinderOptions = Bind_instance_BinderOptions | Get } } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/KnownTypeSymbols.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/KnownTypeSymbols.cs similarity index 100% rename from src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Helpers/KnownTypeSymbols.cs rename to src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Model/KnownTypeSymbols.cs diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/Strings.resx b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/Strings.resx index 9bf38777bde79a..301913987d7c7e 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/Strings.resx +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/Strings.resx @@ -120,6 +120,12 @@ The collection type is not supported: '{0}'. + + Binding logic was not generated for a binder call. Unsupported input patterns include generic calls and passing boxed objects. + + + The target type for a binder call could not be determined + The dictionary key type is not supported: '{0}'. @@ -156,4 +162,10 @@ Did not generate binding logic for a type + + Binding logic was not generated for a binder call with target type '{0}'. Value types are invalid inputs to configuration 'Bind' methods. + + + Value types are invalid inputs to configuration 'Bind' methods + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.cs.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.cs.xlf index 67cc2e5f23ea48..e248c54626865f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.cs.xlf +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.cs.xlf @@ -7,6 +7,16 @@ Typ kolekce se nepodporuje: „{0}“. + + Binding logic was not generated for a binder call. Unsupported input patterns include generic calls and passing boxed objects. + Pro volání vazače se nevygenerovala logika vazby. Nepodporované vstupní vzory zahrnují obecná volání a předávání zabalených objektů. + + + + The target type for a binder call could not be determined + Cílový typ volání vazače nelze určit + + The dictionary key type is not supported: '{0}'. Typ klíče slovníku se nepodporuje:„{0}“. @@ -29,7 +39,7 @@ Cannot create instance of type '{0}' because it is missing a public instance constructor. - Cannot create instance of type '{0}' because it is missing a public instance constructor. + Nelze vytvořit instanci typu „{0}“, protože chybí konstruktor veřejné instance. @@ -39,7 +49,7 @@ Cannot create instance of type '{0}' because it has multiple public parameterized constructors. - Cannot create instance of type '{0}' because it has multiple public parameterized constructors. + Nelze vytvořit instanci typu „{0}“, protože má více veřejných parametrizovaných konstruktorů. @@ -67,6 +77,16 @@ Negenerovala se logika vazby pro typ + + Binding logic was not generated for a binder call with target type '{0}'. Value types are invalid inputs to configuration 'Bind' methods. + Logika vazby nebyla vygenerována pro volání pořadače s cílovým typem „{0}“. Typy hodnot jsou neplatné vstupy pro konfigurační metody Bind. + + + + Value types are invalid inputs to configuration 'Bind' methods + Typy hodnot nejsou platné vstupy pro konfigurační metody „Bind“. + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.de.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.de.xlf index 9c6839a3fd2fac..1fa847592bd02e 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.de.xlf +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.de.xlf @@ -7,6 +7,16 @@ Der Sammlungstyp wird nicht unterstützt: "{0}". + + Binding logic was not generated for a binder call. Unsupported input patterns include generic calls and passing boxed objects. + Für einen Binderaufruf wurde keine Bindungslogik generiert. Nicht unterstützte Eingabemuster umfassen generische Aufrufe und übergeben geschachtelte Objekte. + + + + The target type for a binder call could not be determined + Der Zieltyp für einen Binderaufruf konnte nicht bestimmt werden. + + The dictionary key type is not supported: '{0}'. Der Wörterbuchschlüsseltyp wird nicht unterstützt: "{0}". @@ -29,7 +39,7 @@ Cannot create instance of type '{0}' because it is missing a public instance constructor. - Cannot create instance of type '{0}' because it is missing a public instance constructor. + Die Instanz vom Typ "{0}" kann nicht erstellt werden, weil ein öffentlicher Instanzkonstruktor fehlt. @@ -39,7 +49,7 @@ Cannot create instance of type '{0}' because it has multiple public parameterized constructors. - Cannot create instance of type '{0}' because it has multiple public parameterized constructors. + Die Instanz vom Typ "{0}" kann nicht erstellt werden, weil sie über mehrere öffentliche parametrisierte Konstruktoren verfügt. @@ -67,6 +77,16 @@ Für einen Typ wurde keine Bindungslogik generiert + + Binding logic was not generated for a binder call with target type '{0}'. Value types are invalid inputs to configuration 'Bind' methods. + Für einen Binderaufruf mit dem Zieltyp "{0}" wurde keine Bindungslogik generiert. Werttypen sind ungültige Eingaben für die Konfiguration von Bind-Methoden. + + + + Value types are invalid inputs to configuration 'Bind' methods + Werttypen sind ungültige Eingaben für die Konfiguration von Bind-Methoden. + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.es.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.es.xlf index f876dcd5bd38fb..c52b2317ceaded 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.es.xlf +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.es.xlf @@ -7,6 +7,16 @@ No se admite el tipo de colección: "{0}". + + Binding logic was not generated for a binder call. Unsupported input patterns include generic calls and passing boxed objects. + No se generó la lógica de enlace para una llamada de enlazador. Los patrones de entrada no admitidos incluyen llamadas genéricas y pasar objetos en cuadros. + + + + The target type for a binder call could not be determined + No se pudo determinar el tipo de destino para una llamada de enlazador + + The dictionary key type is not supported: '{0}'. No se admite el tipo de clave de diccionario: "{0}". @@ -29,7 +39,7 @@ Cannot create instance of type '{0}' because it is missing a public instance constructor. - Cannot create instance of type '{0}' because it is missing a public instance constructor. + No se puede crear una instancia de tipo '{0}' porque falta un constructor de instancia pública. @@ -39,7 +49,7 @@ Cannot create instance of type '{0}' because it has multiple public parameterized constructors. - Cannot create instance of type '{0}' because it has multiple public parameterized constructors. + No se puede crear una instancia de tipo '{0}' porque tiene varios constructores con parámetros públicos. @@ -67,6 +77,16 @@ No se ha generado la lógica de enlace para un tipo. + + Binding logic was not generated for a binder call with target type '{0}'. Value types are invalid inputs to configuration 'Bind' methods. + No se generó la lógica de enlace para una llamada de enlazador con el tipo de destino “{0}”. Los tipos de valor son entradas no válidas para los métodos de configuración “'bind”. + + + + Value types are invalid inputs to configuration 'Bind' methods + Los tipos de valor son entradas no válidas para los métodos de configuración “bind” + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.fr.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.fr.xlf index cab1b66b3079be..19362d7336208f 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.fr.xlf +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.fr.xlf @@ -7,6 +7,16 @@ Le type de collection n‘est pas pris en charge : ‘{0}‘. + + Binding logic was not generated for a binder call. Unsupported input patterns include generic calls and passing boxed objects. + La logique de liaison n’a pas été générée pour un appel de classeur. Les modèles d’entrée non pris en charge incluent les appels génériques et les objets boxed de passage. + + + + The target type for a binder call could not be determined + Impossible de déterminer le type cible d’un appel de classeur + + The dictionary key type is not supported: '{0}'. Le type de clé du dictionnaire n’est pas pris en charge : ‘{0}‘. @@ -29,7 +39,7 @@ Cannot create instance of type '{0}' because it is missing a public instance constructor. - Cannot create instance of type '{0}' because it is missing a public instance constructor. + Nous n’avons pas pu créer une instance du type '{0}', car il lui manque un constructeur d’instance public. @@ -39,7 +49,7 @@ Cannot create instance of type '{0}' because it has multiple public parameterized constructors. - Cannot create instance of type '{0}' because it has multiple public parameterized constructors. + Nous n’avons pas pu créer une instance du type '{0}', car il possède plusieurs constructeurs publics paramétrés. @@ -67,6 +77,16 @@ La logique de liaison n’a pas été générée pour un type + + Binding logic was not generated for a binder call with target type '{0}'. Value types are invalid inputs to configuration 'Bind' methods. + La logique de liaison n’a pas été générée pour un appel de classeur avec le type cible '{0}'. Les types valeur ne sont pas des entrées valides pour les méthodes de configuration 'Bind'. + + + + Value types are invalid inputs to configuration 'Bind' methods + Les types valeur ne sont pas des entrées valides pour les méthodes de configuration 'Bind' + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.it.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.it.xlf index a212bd81626656..f418a83d0d422e 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.it.xlf +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.it.xlf @@ -7,6 +7,16 @@ Il tipo di raccolta non è supportato: '{0}'. + + Binding logic was not generated for a binder call. Unsupported input patterns include generic calls and passing boxed objects. + La logica di binding non è stata generata per una chiamata binder. I modelli di input non supportati includono chiamate generiche e il passaggio di oggetti in caselle. + + + + The target type for a binder call could not be determined + Impossibile determinare il tipo di destinazione per una chiamata binder + + The dictionary key type is not supported: '{0}'. Il tipo di chiave del dizionario non è supportato: '{0}'. @@ -29,7 +39,7 @@ Cannot create instance of type '{0}' because it is missing a public instance constructor. - Cannot create instance of type '{0}' because it is missing a public instance constructor. + Non è possibile creare un'istanza di tipo '{0}' perché manca un costruttore di istanza pubblica. @@ -39,7 +49,7 @@ Cannot create instance of type '{0}' because it has multiple public parameterized constructors. - Cannot create instance of type '{0}' because it has multiple public parameterized constructors. + Non è possibile creare un'istanza di tipo '{0}' perché contiene più costruttori con parametri pubblici. @@ -67,6 +77,16 @@ Non è stata generata la logica di binding per un tipo. + + Binding logic was not generated for a binder call with target type '{0}'. Value types are invalid inputs to configuration 'Bind' methods. + La logica di binding non è stata generata per una chiamata binder con tipo di destinazione '{0}'. I tipi di valore sono input non validi per i metodi di configurazione 'Bind'. + + + + Value types are invalid inputs to configuration 'Bind' methods + I tipi di valore sono input non validi per i metodi di configurazione 'Bind' + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ja.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ja.xlf index b6c9407b5d16dd..ba59cfba40a89b 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ja.xlf +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ja.xlf @@ -7,6 +7,16 @@ コレクション型はサポートされていません: '{0}'。 + + Binding logic was not generated for a binder call. Unsupported input patterns include generic calls and passing boxed objects. + バインダー呼び出しのバインド ロジックが生成されませんでした。サポートされていない入力パターンとしては、ジェネリック呼び出し、ボックス化されたオブジェクトの受け渡しなどがあります。 + + + + The target type for a binder call could not be determined + バインダー呼び出しの対象の型を特定できませんでした + + The dictionary key type is not supported: '{0}'. 辞書キー型はサポートされていません: '{0}'。 @@ -29,7 +39,7 @@ Cannot create instance of type '{0}' because it is missing a public instance constructor. - Cannot create instance of type '{0}' because it is missing a public instance constructor. + パブリック インスタンス コンストラクターがないため、型 '{0}' のインスタンスを作成できません。 @@ -39,7 +49,7 @@ Cannot create instance of type '{0}' because it has multiple public parameterized constructors. - Cannot create instance of type '{0}' because it has multiple public parameterized constructors. + 複数のパブリック パラメーター化コンストラクターがあるため、型 '{0}' のインスタンスを作成できません。 @@ -67,6 +77,16 @@ 型のバインディング ロジックを生成しませんでした + + Binding logic was not generated for a binder call with target type '{0}'. Value types are invalid inputs to configuration 'Bind' methods. + 対象の型が '{0}' のバインダー呼び出しについてバインド ロジックが生成されませんでした。値の型が、構成の 'Bind' メソッドへの入力として正しくありません。 + + + + Value types are invalid inputs to configuration 'Bind' methods + 値の型が、構成の 'Bind' メソッドへの入力として正しくありません + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ko.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ko.xlf index 0bd5f2f45bbdb6..10b9b107c4aade 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ko.xlf +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ko.xlf @@ -7,6 +7,16 @@ 컬렉션 유형이 지원되지 않습니다: '{0}'. + + Binding logic was not generated for a binder call. Unsupported input patterns include generic calls and passing boxed objects. + 바인더 호출에 대한 바인딩 논리가 생성되지 않았습니다. 지원되지 않는 입력 패턴에는 제네릭 호출 및 boxed 개체 전달이 포함됩니다. + + + + The target type for a binder call could not be determined + 바인더 호출의 대상 유형을 확인할 수 없습니다. + + The dictionary key type is not supported: '{0}'. 사전 키 유형이 지원되지 않습니다: '{0}'. @@ -29,7 +39,7 @@ Cannot create instance of type '{0}' because it is missing a public instance constructor. - Cannot create instance of type '{0}' because it is missing a public instance constructor. + 공용 인스턴스 생성자가 없으므로 '{0}' 형식의 인스턴스를 만들 수 없습니다. @@ -39,7 +49,7 @@ Cannot create instance of type '{0}' because it has multiple public parameterized constructors. - Cannot create instance of type '{0}' because it has multiple public parameterized constructors. + 매개 변수가 있는 공용 생성자가 여러 개 있으므로 '{0}' 형식의 인스턴스를 만들 수 없습니다. @@ -67,6 +77,16 @@ 형식에 대한 바인딩 논리를 생성하지 않았습니다. + + Binding logic was not generated for a binder call with target type '{0}'. Value types are invalid inputs to configuration 'Bind' methods. + 대상 유형이 '{0}'인 바인더 호출에 대해 바인딩 논리가 생성되지 않았습니다. 값 유형은 구성 '바인딩' 방법에 대한 유효하지 않은 입력입니다. + + + + Value types are invalid inputs to configuration 'Bind' methods + 값 형식은 구성 'Bind' 메서드에 대한 잘못된 입력입니다. + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.pl.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.pl.xlf index aeb93e0bfb93ee..2b558c588ebfb9 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.pl.xlf +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.pl.xlf @@ -7,6 +7,16 @@ Typ kolekcji nie jest obsługiwany: „{0}”. + + Binding logic was not generated for a binder call. Unsupported input patterns include generic calls and passing boxed objects. + Nie wygenerowano logiki powiązania dla wywołania integratora. Nieobsługiwane wzorce wejściowe obejmują wywołania ogólne i przekazywanie obiektów w ramce. + + + + The target type for a binder call could not be determined + Nie można określić typu docelowego dla wywołania integratora + + The dictionary key type is not supported: '{0}'. Typ klucza słownika nie jest obsługiwany: „{0}”. @@ -29,7 +39,7 @@ Cannot create instance of type '{0}' because it is missing a public instance constructor. - Cannot create instance of type '{0}' because it is missing a public instance constructor. + Nie można utworzyć wystąpienia typu „{0}”, ponieważ brakuje w nim konstruktora wystąpienia publicznego. @@ -39,7 +49,7 @@ Cannot create instance of type '{0}' because it has multiple public parameterized constructors. - Cannot create instance of type '{0}' because it has multiple public parameterized constructors. + Nie można utworzyć wystąpienia typu „{0}”, ponieważ ma ono wiele publicznych konstruktorów sparametryzowanych. @@ -67,6 +77,16 @@ Nie wygenerowano logiki powiązania dla typu + + Binding logic was not generated for a binder call with target type '{0}'. Value types are invalid inputs to configuration 'Bind' methods. + Nie wygenerowano logiki powiązania dla wywołania integratora z typem docelowym „{0}”. Typy wartości to nieprawidłowe dane wejściowe do konfiguracji metod „Powiązanie”. + + + + Value types are invalid inputs to configuration 'Bind' methods + Typy wartości to nieprawidłowe dane wejściowe do konfiguracji metod „Powiązanie” + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.pt-BR.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.pt-BR.xlf index 8e8254c995d9f6..9d2a51c6aa9c96 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.pt-BR.xlf +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.pt-BR.xlf @@ -7,6 +7,16 @@ O tipo de coleção não é compatível: '{0}'. + + Binding logic was not generated for a binder call. Unsupported input patterns include generic calls and passing boxed objects. + A lógica de associação não foi gerada para uma chamada de associador. Os padrões de entrada sem suporte incluem chamadas genéricas e passagem de objetos em caixa. + + + + The target type for a binder call could not be determined + Não foi possível determinar o tipo de destino de uma chamada de associador + + The dictionary key type is not supported: '{0}'. O tipo de chave do dicionário não é suportado: '{0}'. @@ -29,7 +39,7 @@ Cannot create instance of type '{0}' because it is missing a public instance constructor. - Cannot create instance of type '{0}' because it is missing a public instance constructor. + Não é possível criar instância do tipo ''{0}'' porque falta um construtor de instância pública. @@ -39,7 +49,7 @@ Cannot create instance of type '{0}' because it has multiple public parameterized constructors. - Cannot create instance of type '{0}' because it has multiple public parameterized constructors. + Não é possível criar instância do tipo ''{0}'' porque ela tem vários construtores parametrizados públicos. @@ -67,6 +77,16 @@ Não gerou lógica de ligação para um tipo + + Binding logic was not generated for a binder call with target type '{0}'. Value types are invalid inputs to configuration 'Bind' methods. + A lógica de associação não foi gerada para uma chamada de associador com o tipo de destino "{0}". Tipos de valor são entradas inválidas para métodos de configuração 'Bind'. + + + + Value types are invalid inputs to configuration 'Bind' methods + Tipos de valor são entradas inválidas para métodos de configuração "Associar" + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ru.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ru.xlf index eba8abf1e9fd4e..1ed03c55891a9e 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ru.xlf +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.ru.xlf @@ -7,6 +7,16 @@ Тип коллекции не поддерживается: "{0}". + + Binding logic was not generated for a binder call. Unsupported input patterns include generic calls and passing boxed objects. + Логика привязки не была создана для вызова модуля привязки. К неподдерживаемым шаблонам ввода относятся универсальные вызовы и передача упакованных объектов. + + + + The target type for a binder call could not be determined + Не удалось определить целевой тип для вызова модуля привязки + + The dictionary key type is not supported: '{0}'. Тип ключа словаря не поддерживается: "{0}". @@ -29,7 +39,7 @@ Cannot create instance of type '{0}' because it is missing a public instance constructor. - Cannot create instance of type '{0}' because it is missing a public instance constructor. + Не удается создать экземпляр типа "{0}", так как в нем отсутствует конструктор общедоступных экземпляров. @@ -39,7 +49,7 @@ Cannot create instance of type '{0}' because it has multiple public parameterized constructors. - Cannot create instance of type '{0}' because it has multiple public parameterized constructors. + Не удается создать экземпляр типа "{0}", так как он содержит несколько общедоступных параметров конструкторов. @@ -67,6 +77,16 @@ Не создана логика привязки для типа + + Binding logic was not generated for a binder call with target type '{0}'. Value types are invalid inputs to configuration 'Bind' methods. + Логика привязки не была создана для вызова модуля привязки с типом "{0}". Типы значений являются недопустимыми входными данными для методов "Bind" конфигурации. + + + + Value types are invalid inputs to configuration 'Bind' methods + Типы значений являются недопустимыми входными данными для методов "Bind" конфигурации + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.tr.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.tr.xlf index ecb3ba09f40824..8a6dbf76bab7f7 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.tr.xlf +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.tr.xlf @@ -7,6 +7,16 @@ Koleksiyon türü desteklenmiyor: '{0}'. + + Binding logic was not generated for a binder call. Unsupported input patterns include generic calls and passing boxed objects. + Bir bağlayıcı çağrısı için bağlama mantığı oluşturulmadı. Desteklenmeyen giriş desenleri genel çağrılar ve geçici kutulu nesneler içeriyor. + + + + The target type for a binder call could not be determined + Bir bağlayıcı çağrısının hedef türü belirlenemedi + + The dictionary key type is not supported: '{0}'. Sözlük anahtarı türü desteklenmiyor: '{0}'. @@ -29,7 +39,7 @@ Cannot create instance of type '{0}' because it is missing a public instance constructor. - Cannot create instance of type '{0}' because it is missing a public instance constructor. + Ortak örnek oluşturucu içermediğinden '{0}' türündeki örnek oluşturulamıyor. @@ -39,7 +49,7 @@ Cannot create instance of type '{0}' because it has multiple public parameterized constructors. - Cannot create instance of type '{0}' because it has multiple public parameterized constructors. + Birden çok ortak parametreli oluşturucu içerdiğinden '{0}' türündeki örnek oluşturulamıyor. @@ -67,6 +77,16 @@ Bir tür için bağlama mantığı oluşturulmadı + + Binding logic was not generated for a binder call with target type '{0}'. Value types are invalid inputs to configuration 'Bind' methods. + '{0}' hedef türüne sahip bir bağlayıcı çağrısı için bağlama mantığı oluşturulmadı. Değer türleri yapılandırma ‘Bağlama’ yöntemleri için geçersiz girişlerdir. + + + + Value types are invalid inputs to configuration 'Bind' methods + Değer türleri yapılandırma ‘Bağlama’ yöntemleri için geçersiz girişlerdir + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.zh-Hans.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.zh-Hans.xlf index 6ca3d43c80c6b9..9d0c0eb3a5d6dd 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.zh-Hans.xlf @@ -7,6 +7,16 @@ 不支持此集合类型 '{0}'。 + + Binding logic was not generated for a binder call. Unsupported input patterns include generic calls and passing boxed objects. + 未为联编程序调用生成绑定逻辑。不支持的输入模式包括泛型调用和传递装箱对象。 + + + + The target type for a binder call could not be determined + 联编程序调用的目标类型无法确定 + + The dictionary key type is not supported: '{0}'. 不支持此字典密钥类型: '{0}'。 @@ -29,7 +39,7 @@ Cannot create instance of type '{0}' because it is missing a public instance constructor. - Cannot create instance of type '{0}' because it is missing a public instance constructor. + 无法创建类型“{0}”的实例,因为它缺少公共实例构造函数。 @@ -39,7 +49,7 @@ Cannot create instance of type '{0}' because it has multiple public parameterized constructors. - Cannot create instance of type '{0}' because it has multiple public parameterized constructors. + 无法创建类型“{0}”的实例,因为它具有多个公共参数化构造函数。 @@ -67,6 +77,16 @@ 没有为类型生成绑定逻辑 + + Binding logic was not generated for a binder call with target type '{0}'. Value types are invalid inputs to configuration 'Bind' methods. + 没有为目标类型为“{0}”的绑定器调用生成绑定逻辑。值类型是配置“Bind”方法的无效输入。 + + + + Value types are invalid inputs to configuration 'Bind' methods + 值类型是配置“Bind”方法的无效输入 + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.zh-Hant.xlf b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.zh-Hant.xlf index 64cde87ba66ec9..dc6ded618c8e94 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Resources/xlf/Strings.zh-Hant.xlf @@ -7,6 +7,16 @@ 不支援集合類型: '{0}'。 + + Binding logic was not generated for a binder call. Unsupported input patterns include generic calls and passing boxed objects. + 未產生文件夾呼叫的繫結邏輯。不支援的輸入模式包括一般呼叫和傳遞方塊物件。 + + + + The target type for a binder call could not be determined + 無法判斷文件夾呼叫的目標型別 + + The dictionary key type is not supported: '{0}'. 不支援字典索引鍵類型: '{0}'。 @@ -29,7 +39,7 @@ Cannot create instance of type '{0}' because it is missing a public instance constructor. - Cannot create instance of type '{0}' because it is missing a public instance constructor. + 無法建立類型為 '{0}' 的執行個體,因為它缺少公用執行個體建構函式。 @@ -39,7 +49,7 @@ Cannot create instance of type '{0}' because it has multiple public parameterized constructors. - Cannot create instance of type '{0}' because it has multiple public parameterized constructors. + 無法建立類型為 '{0}' 的執行個體,因為它有多個公用參數化建構函式。 @@ -67,6 +77,16 @@ 未產生類型的繫結邏輯 + + Binding logic was not generated for a binder call with target type '{0}'. Value types are invalid inputs to configuration 'Bind' methods. + 未針對目標型別為 '{0}' 的文件夾呼叫產生繫結邏輯。實值型別對設定 'Bind' 方法的輸入無效。 + + + + Value types are invalid inputs to configuration 'Bind' methods + 實值型別對設定 'Bind' 方法的輸入無效 + + \ No newline at end of file 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 a184211cc12c4f..fadaa1c0e69f1b 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 @@ -216,49 +216,57 @@ public void GetUintEnumDictionary() Assert.Equal("val_3", options[KeyUintEnum.ghi]); } - [ConditionalFact(typeof(TestHelpers), nameof(TestHelpers.NotSourceGenMode))] // Reflection fallback: generic type info not supported with source gen. + // Reflection fallback: generic type info not supported with source gen. + [ConditionalFact(typeof(TestHelpers), nameof(TestHelpers.NotSourceGenMode))] public void GetSByteDictionary() { GetIntDictionaryT(0, 1, 2); } - [ConditionalFact(typeof(TestHelpers), nameof(TestHelpers.NotSourceGenMode))] // Reflection fallback: generic type info not supported with source gen. + // Reflection fallback: generic type info not supported with source gen. + [ConditionalFact(typeof(TestHelpers), nameof(TestHelpers.NotSourceGenMode))] public void GetByteDictionary() { GetIntDictionaryT(0, 1, 2); } - [ConditionalFact(typeof(TestHelpers), nameof(TestHelpers.NotSourceGenMode))] // Reflection fallback: generic type info not supported with source gen. + // Reflection fallback: generic type info not supported with source gen. + [ConditionalFact(typeof(TestHelpers), nameof(TestHelpers.NotSourceGenMode))] public void GetShortDictionary() { GetIntDictionaryT(0, 1, 2); } - [ConditionalFact(typeof(TestHelpers), nameof(TestHelpers.NotSourceGenMode))] // Reflection fallback: generic type info not supported with source gen. + // Reflection fallback: generic type info not supported with source gen. + [ConditionalFact(typeof(TestHelpers), nameof(TestHelpers.NotSourceGenMode))] public void GetUShortDictionary() { GetIntDictionaryT(0, 1, 2); } - [ConditionalFact(typeof(TestHelpers), nameof(TestHelpers.NotSourceGenMode))] // Reflection fallback: generic type info not supported with source gen. + // Reflection fallback: generic type info not supported with source gen. + [ConditionalFact(typeof(TestHelpers), nameof(TestHelpers.NotSourceGenMode))] public void GetIntDictionary() { GetIntDictionaryT(0, 1, 2); } - [ConditionalFact(typeof(TestHelpers), nameof(TestHelpers.NotSourceGenMode))] // Reflection fallback: generic type info not supported with source gen. + // Reflection fallback: generic type info not supported with source gen. + [ConditionalFact(typeof(TestHelpers), nameof(TestHelpers.NotSourceGenMode))] public void GetUIntDictionary() { GetIntDictionaryT(0, 1, 2); } - [ConditionalFact(typeof(TestHelpers), nameof(TestHelpers.NotSourceGenMode))] // Reflection fallback: generic type info not supported with source gen. + // Reflection fallback: generic type info not supported with source gen. + [ConditionalFact(typeof(TestHelpers), nameof(TestHelpers.NotSourceGenMode))] public void GetLongDictionary() { GetIntDictionaryT(0, 1, 2); } - [ConditionalFact(typeof(TestHelpers), nameof(TestHelpers.NotSourceGenMode))] // Reflection fallback: generic type info not supported with source gen. + // Reflection fallback: generic type info not supported with source gen. + [ConditionalFact(typeof(TestHelpers), nameof(TestHelpers.NotSourceGenMode))] public void GetULongDictionary() { GetIntDictionaryT(0, 1, 2); 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 6e30c7400d78af..c2068feefb6d01 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 @@ -637,5 +637,23 @@ public record RecordWithPrimitives public TimeOnly Prop22 { get; set; } #endif } + + public class ClassWithParameterlessAndParameterizedCtor + { + public ClassWithParameterlessAndParameterizedCtor() => MyInt = 1; + + public ClassWithParameterlessAndParameterizedCtor(int myInt) => MyInt = 10; + + public int MyInt { get; } + } + + public struct StructWithParameterlessAndParameterizedCtor + { + public StructWithParameterlessAndParameterizedCtor() => MyInt = 1; + + public StructWithParameterlessAndParameterizedCtor(int myInt) => MyInt = 10; + + public int MyInt { get; } + } } } 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 ec29f212b60f4e..75377493a423bf 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs @@ -1855,22 +1855,20 @@ public void ForStructs_ParameterlessConstructorIsPickedOverParameterized() Assert.Equal(1, obj.MyInt); } - public class ClassWithParameterlessAndParameterizedCtor - { - public ClassWithParameterlessAndParameterizedCtor() => MyInt = 1; - - public ClassWithParameterlessAndParameterizedCtor(int myInt) => MyInt = 10; - - public int MyInt { get; } - } - - public struct StructWithParameterlessAndParameterizedCtor + [Fact] + public void BindRootStructIsNoOp() { - public StructWithParameterlessAndParameterizedCtor() => MyInt = 1; - - public StructWithParameterlessAndParameterizedCtor(int myInt) => MyInt = 10; + var configuration = TestHelpers.GetConfigurationFromJsonString(""" + { + "Int32": 9, + "Boolean": true, + } + """); - public int MyInt { get; } + StructWithNestedStructs.DeeplyNested obj = new(); + configuration.Bind(obj); + Assert.Equal(0, obj.Int32); + Assert.False(obj.Boolean); } } } diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/TestBindCallGen.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Bind.generated.txt similarity index 100% rename from src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/TestBindCallGen.generated.txt rename to src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Bind.generated.txt diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Bind_Instance.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Bind_Instance.generated.txt new file mode 100644 index 00000000000000..280ad976830a54 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Bind_Instance.generated.txt @@ -0,0 +1,180 @@ +// +#nullable enable + +internal static class GeneratedConfigurationBinder +{ + public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::Program.MyClass obj) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.BindCore(configuration, ref obj, binderOptions: null); +} + +namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration +{ + using Microsoft.Extensions.Configuration; + using System; + using System.Collections.Generic; + using System.Globalization; + + internal static class Helpers + { + public static void BindCore(IConfiguration configuration, ref List obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + foreach (IConfigurationSection section in configuration.GetChildren()) + { + int element; + if (section.Value is string stringValue0) + { + element = ParseInt(stringValue0, () => section.Path); + obj.Add(element); + } + } + } + + public static void BindCore(IConfiguration configuration, ref Dictionary obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + foreach (IConfigurationSection section in configuration.GetChildren()) + { + string key = section.Key; + if (section.Value is string stringValue1) + { + obj[key] = stringValue1; + } + } + } + + public static void BindCore(IConfiguration configuration, ref Program.MyClass2 obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + } + + public static void BindCore(IConfiguration configuration, ref Dictionary obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + foreach (IConfigurationSection section in configuration.GetChildren()) + { + string key = section.Key; + if (!(obj.TryGetValue(key, out Program.MyClass2? element) && element is not null)) + { + element = new Program.MyClass2(); + } + BindCore(section, ref element!, binderOptions); + obj[key] = element; + } + } + + public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + List? temp = null; + foreach (IConfigurationSection section in configuration.GetChildren()) + { + switch (section.Key) + { + case "MyString": + { + if (configuration["MyString"] is string stringValue3) + { + obj.MyString = stringValue3; + } + } + break; + case "MyInt": + { + if (configuration["MyInt"] is string stringValue4) + { + obj.MyInt = ParseInt(stringValue4, () => section.Path); + } + } + break; + case "MyList": + { + if (HasChildren(section)) + { + List temp5 = obj.MyList; + temp5 ??= new List(); + BindCore(section, ref temp5, binderOptions); + obj.MyList = temp5; + } + } + break; + case "MyDictionary": + { + if (HasChildren(section)) + { + Dictionary temp6 = obj.MyDictionary; + temp6 ??= new Dictionary(); + BindCore(section, ref temp6, binderOptions); + obj.MyDictionary = temp6; + } + } + break; + case "MyComplexDictionary": + { + if (HasChildren(section)) + { + Dictionary temp7 = obj.MyComplexDictionary; + temp7 ??= new Dictionary(); + BindCore(section, ref temp7, binderOptions); + obj.MyComplexDictionary = temp7; + } + } + break; + default: + { + if (binderOptions?.ErrorOnUnknownConfiguration == true) + { + (temp ??= new List()).Add($"'{section.Key}'"); + } + } + break; + } + } + + if (temp is not null) + { + throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass)}: {string.Join(", ", temp)}"); + } + } + + public static bool HasChildren(IConfiguration configuration) + { + foreach (IConfigurationSection section in configuration.GetChildren()) + { + return true; + } + return false; + } + + public static int ParseInt(string stringValue, Func getPath) + { + try + { + return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture); + } + catch (Exception exception) + { + throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Bind_Instance_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Bind_Instance_BinderOptions.generated.txt new file mode 100644 index 00000000000000..bf816b9543cad1 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Bind_Instance_BinderOptions.generated.txt @@ -0,0 +1,195 @@ +// +#nullable enable + +internal static class GeneratedConfigurationBinder +{ + public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::Program.MyClass obj, global::System.Action? configureOptions) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.BindCore(configuration, ref obj, global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.GetBinderOptions(configureOptions)); +} + +namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration +{ + using Microsoft.Extensions.Configuration; + using System; + using System.Collections.Generic; + using System.Globalization; + + internal static class Helpers + { + public static void BindCore(IConfiguration configuration, ref List obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + foreach (IConfigurationSection section in configuration.GetChildren()) + { + int element; + if (section.Value is string stringValue0) + { + element = ParseInt(stringValue0, () => section.Path); + obj.Add(element); + } + } + } + + public static void BindCore(IConfiguration configuration, ref Dictionary obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + foreach (IConfigurationSection section in configuration.GetChildren()) + { + string key = section.Key; + if (section.Value is string stringValue1) + { + obj[key] = stringValue1; + } + } + } + + public static void BindCore(IConfiguration configuration, ref Program.MyClass2 obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + } + + public static void BindCore(IConfiguration configuration, ref Dictionary obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + foreach (IConfigurationSection section in configuration.GetChildren()) + { + string key = section.Key; + if (!(obj.TryGetValue(key, out Program.MyClass2? element) && element is not null)) + { + element = new Program.MyClass2(); + } + BindCore(section, ref element!, binderOptions); + obj[key] = element; + } + } + + public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + List? temp = null; + foreach (IConfigurationSection section in configuration.GetChildren()) + { + switch (section.Key) + { + case "MyString": + { + if (configuration["MyString"] is string stringValue3) + { + obj.MyString = stringValue3; + } + } + break; + case "MyInt": + { + if (configuration["MyInt"] is string stringValue4) + { + obj.MyInt = ParseInt(stringValue4, () => section.Path); + } + } + break; + case "MyList": + { + if (HasChildren(section)) + { + List temp5 = obj.MyList; + temp5 ??= new List(); + BindCore(section, ref temp5, binderOptions); + obj.MyList = temp5; + } + } + break; + case "MyDictionary": + { + if (HasChildren(section)) + { + Dictionary temp6 = obj.MyDictionary; + temp6 ??= new Dictionary(); + BindCore(section, ref temp6, binderOptions); + obj.MyDictionary = temp6; + } + } + break; + case "MyComplexDictionary": + { + if (HasChildren(section)) + { + Dictionary temp7 = obj.MyComplexDictionary; + temp7 ??= new Dictionary(); + BindCore(section, ref temp7, binderOptions); + obj.MyComplexDictionary = temp7; + } + } + break; + default: + { + if (binderOptions?.ErrorOnUnknownConfiguration == true) + { + (temp ??= new List()).Add($"'{section.Key}'"); + } + } + break; + } + } + + if (temp is not null) + { + throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass)}: {string.Join(", ", temp)}"); + } + } + + public static bool HasChildren(IConfiguration configuration) + { + foreach (IConfigurationSection section in configuration.GetChildren()) + { + return true; + } + return false; + } + + public static BinderOptions? GetBinderOptions(System.Action? configureOptions) + { + if (configureOptions is null) + { + return null; + } + BinderOptions binderOptions = new(); + configureOptions(binderOptions); + if (binderOptions.BindNonPublicProperties) + { + throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'."); + } + return binderOptions; + } + + public static int ParseInt(string stringValue, Func getPath) + { + try + { + return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture); + } + catch (Exception exception) + { + throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Bind_Key_Instance.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Bind_Key_Instance.generated.txt new file mode 100644 index 00000000000000..466637a43bbb9d --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Bind_Key_Instance.generated.txt @@ -0,0 +1,180 @@ +// +#nullable enable + +internal static class GeneratedConfigurationBinder +{ + public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, string key, global::Program.MyClass obj) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.BindCore(configuration.GetSection(key), ref obj, binderOptions: null); +} + +namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration +{ + using Microsoft.Extensions.Configuration; + using System; + using System.Collections.Generic; + using System.Globalization; + + internal static class Helpers + { + public static void BindCore(IConfiguration configuration, ref List obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + foreach (IConfigurationSection section in configuration.GetChildren()) + { + int element; + if (section.Value is string stringValue0) + { + element = ParseInt(stringValue0, () => section.Path); + obj.Add(element); + } + } + } + + public static void BindCore(IConfiguration configuration, ref Dictionary obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + foreach (IConfigurationSection section in configuration.GetChildren()) + { + string key = section.Key; + if (section.Value is string stringValue1) + { + obj[key] = stringValue1; + } + } + } + + public static void BindCore(IConfiguration configuration, ref Program.MyClass2 obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + } + + public static void BindCore(IConfiguration configuration, ref Dictionary obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + foreach (IConfigurationSection section in configuration.GetChildren()) + { + string key = section.Key; + if (!(obj.TryGetValue(key, out Program.MyClass2? element) && element is not null)) + { + element = new Program.MyClass2(); + } + BindCore(section, ref element!, binderOptions); + obj[key] = element; + } + } + + public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + List? temp = null; + foreach (IConfigurationSection section in configuration.GetChildren()) + { + switch (section.Key) + { + case "MyString": + { + if (configuration["MyString"] is string stringValue3) + { + obj.MyString = stringValue3; + } + } + break; + case "MyInt": + { + if (configuration["MyInt"] is string stringValue4) + { + obj.MyInt = ParseInt(stringValue4, () => section.Path); + } + } + break; + case "MyList": + { + if (HasChildren(section)) + { + List temp5 = obj.MyList; + temp5 ??= new List(); + BindCore(section, ref temp5, binderOptions); + obj.MyList = temp5; + } + } + break; + case "MyDictionary": + { + if (HasChildren(section)) + { + Dictionary temp6 = obj.MyDictionary; + temp6 ??= new Dictionary(); + BindCore(section, ref temp6, binderOptions); + obj.MyDictionary = temp6; + } + } + break; + case "MyComplexDictionary": + { + if (HasChildren(section)) + { + Dictionary temp7 = obj.MyComplexDictionary; + temp7 ??= new Dictionary(); + BindCore(section, ref temp7, binderOptions); + obj.MyComplexDictionary = temp7; + } + } + break; + default: + { + if (binderOptions?.ErrorOnUnknownConfiguration == true) + { + (temp ??= new List()).Add($"'{section.Key}'"); + } + } + break; + } + } + + if (temp is not null) + { + throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass)}: {string.Join(", ", temp)}"); + } + } + + public static bool HasChildren(IConfiguration configuration) + { + foreach (IConfigurationSection section in configuration.GetChildren()) + { + return true; + } + return false; + } + + public static int ParseInt(string stringValue, Func getPath) + { + try + { + return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture); + } + catch (Exception exception) + { + throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/TestCollectionsGen.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Collections.generated.txt similarity index 93% rename from src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/TestCollectionsGen.generated.txt rename to src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Collections.generated.txt index e10a7f436cf755..96233267179cc5 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/TestCollectionsGen.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Collections.generated.txt @@ -213,6 +213,21 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration return false; } + public static BinderOptions? GetBinderOptions(System.Action? configureOptions) + { + if (configureOptions is null) + { + return null; + } + BinderOptions binderOptions = new(); + configureOptions(binderOptions); + if (binderOptions.BindNonPublicProperties) + { + throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'."); + } + return binderOptions; + } + public static int ParseInt(string stringValue, Func getPath) { try diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/TestConfigureCallGen.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Configure.generated.txt similarity index 100% rename from src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/TestConfigureCallGen.generated.txt rename to src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Configure.generated.txt diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/TestGetCallGen.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Get.generated.txt similarity index 100% rename from src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/TestGetCallGen.generated.txt rename to src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Get.generated.txt diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/TestGetValueCallGen.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/GetValue.generated.txt similarity index 96% rename from src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/TestGetValueCallGen.generated.txt rename to src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/GetValue.generated.txt index ed3c062c6729de..753a62bb0bbf76 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/TestGetValueCallGen.generated.txt +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/GetValue.generated.txt @@ -9,7 +9,7 @@ internal static class GeneratedConfigurationBinder public static object? GetValue(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type, string key) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.GetValueCore(configuration, type, key); - public static object? GetValue(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type, string key, object? defaultValue) =>global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.GetValueCore(configuration, type, key) ?? defaultValue; + public static object? GetValue(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type, string key, object? defaultValue) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.GetValueCore(configuration, type, key) ?? defaultValue; } namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/GetValue_T_Key.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/GetValue_T_Key.generated.txt new file mode 100644 index 00000000000000..d57c4e65db6edf --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/GetValue_T_Key.generated.txt @@ -0,0 +1,52 @@ +// +#nullable enable + +internal static class GeneratedConfigurationBinder +{ + public static T? GetValue(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, string key) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.GetValueCore(configuration, typeof(T), key) ?? default(T)); +} + +namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration +{ + using Microsoft.Extensions.Configuration; + using System; + using System.Collections.Generic; + using System.Globalization; + + internal static class Helpers + { + public static object? GetValueCore(this IConfiguration configuration, Type type, string key) + { + if (configuration is null) + { + throw new ArgumentNullException(nameof(configuration)); + } + + IConfigurationSection section = configuration.GetSection(key); + object? obj; + + if (type == typeof(int)) + { + if (section.Value is string stringValue0) + { + obj = ParseInt(stringValue0, () => section.Path); + return obj; + } + } + + return null; + } + + public static int ParseInt(string stringValue, Func getPath) + { + try + { + return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture); + } + catch (Exception exception) + { + throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/GetValue_T_Key_DefaultValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/GetValue_T_Key_DefaultValue.generated.txt new file mode 100644 index 00000000000000..c4dac1baa51599 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/GetValue_T_Key_DefaultValue.generated.txt @@ -0,0 +1,52 @@ +// +#nullable enable + +internal static class GeneratedConfigurationBinder +{ + public static T? GetValue(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, string key, T defaultValue) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.GetValueCore(configuration, typeof(T), key) ?? defaultValue); +} + +namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration +{ + using Microsoft.Extensions.Configuration; + using System; + using System.Collections.Generic; + using System.Globalization; + + internal static class Helpers + { + public static object? GetValueCore(this IConfiguration configuration, Type type, string key) + { + if (configuration is null) + { + throw new ArgumentNullException(nameof(configuration)); + } + + IConfigurationSection section = configuration.GetSection(key); + object? obj; + + if (type == typeof(int)) + { + if (section.Value is string stringValue0) + { + obj = ParseInt(stringValue0, () => section.Path); + return obj; + } + } + + return null; + } + + public static int ParseInt(string stringValue, Func getPath) + { + try + { + return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture); + } + catch (Exception exception) + { + throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/GetValue_TypeOf_Key.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/GetValue_TypeOf_Key.generated.txt new file mode 100644 index 00000000000000..944ea17b4311be --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/GetValue_TypeOf_Key.generated.txt @@ -0,0 +1,52 @@ +// +#nullable enable + +internal static class GeneratedConfigurationBinder +{ + public static object? GetValue(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type, string key) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.GetValueCore(configuration, type, key); +} + +namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration +{ + using Microsoft.Extensions.Configuration; + using System; + using System.Collections.Generic; + using System.Globalization; + + internal static class Helpers + { + public static object? GetValueCore(this IConfiguration configuration, Type type, string key) + { + if (configuration is null) + { + throw new ArgumentNullException(nameof(configuration)); + } + + IConfigurationSection section = configuration.GetSection(key); + object? obj; + + if (type == typeof(bool?)) + { + if (section.Value is string stringValue0) + { + obj = ParseBool(stringValue0, () => section.Path); + return obj; + } + } + + return null; + } + + public static bool ParseBool(string stringValue, Func getPath) + { + try + { + return bool.Parse(stringValue); + } + catch (Exception exception) + { + throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(bool)}'.", exception); + } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/GetValue_TypeOf_Key_DefaultValue.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/GetValue_TypeOf_Key_DefaultValue.generated.txt new file mode 100644 index 00000000000000..c622af422b23ae --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/GetValue_TypeOf_Key_DefaultValue.generated.txt @@ -0,0 +1,52 @@ +// +#nullable enable + +internal static class GeneratedConfigurationBinder +{ + public static object? GetValue(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type, string key, object? defaultValue) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.GetValueCore(configuration, type, key) ?? defaultValue; +} + +namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration +{ + using Microsoft.Extensions.Configuration; + using System; + using System.Collections.Generic; + using System.Globalization; + + internal static class Helpers + { + public static object? GetValueCore(this IConfiguration configuration, Type type, string key) + { + if (configuration is null) + { + throw new ArgumentNullException(nameof(configuration)); + } + + IConfigurationSection section = configuration.GetSection(key); + object? obj; + + if (type == typeof(CultureInfo)) + { + if (section.Value is string stringValue0) + { + obj = ParseCultureInfo(stringValue0, () => section.Path); + return obj; + } + } + + return null; + } + + public static CultureInfo ParseCultureInfo(string stringValue, Func getPath) + { + try + { + return CultureInfo.GetCultureInfo(stringValue); + } + catch (Exception exception) + { + throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(CultureInfo)}'.", exception); + } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Get_T.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Get_T.generated.txt new file mode 100644 index 00000000000000..896d7e9669ee28 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Get_T.generated.txt @@ -0,0 +1,214 @@ +// +#nullable enable + +internal static class GeneratedConfigurationBinder +{ + public static T? Get(this global::Microsoft.Extensions.Configuration.IConfiguration configuration) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.GetCore(configuration, typeof(T), configureOptions: null) ?? default(T)); +} + +namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration +{ + using Microsoft.Extensions.Configuration; + using System; + using System.Collections.Generic; + using System.Globalization; + + internal static class Helpers + { + public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions) + { + if (configuration is null) + { + throw new ArgumentNullException(nameof(configuration)); + } + + BinderOptions? binderOptions = GetBinderOptions(configureOptions); + + if (!HasValueOrChildren(configuration)) + { + return null; + } + + if (type == typeof(Program.MyClass)) + { + var obj = new Program.MyClass(); + BindCore(configuration, ref obj, binderOptions); + return obj; + } + + throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input."); + } + + public static void BindCore(IConfiguration configuration, ref List obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + foreach (IConfigurationSection section in configuration.GetChildren()) + { + int element; + if (section.Value is string stringValue1) + { + element = ParseInt(stringValue1, () => section.Path); + obj.Add(element); + } + } + } + + public static void BindCore(IConfiguration configuration, ref int[] obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + var temp2 = new List(); + BindCore(configuration, ref temp2, binderOptions); + int originalCount = obj.Length; + Array.Resize(ref obj, originalCount + temp2.Count); + temp2.CopyTo(obj, originalCount); + } + + public static void BindCore(IConfiguration configuration, ref Dictionary obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + foreach (IConfigurationSection section in configuration.GetChildren()) + { + string key = section.Key; + if (section.Value is string stringValue4) + { + obj[key] = stringValue4; + } + } + } + + public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + List? temp = null; + foreach (IConfigurationSection section in configuration.GetChildren()) + { + switch (section.Key) + { + case "MyString": + { + if (configuration["MyString"] is string stringValue5) + { + obj.MyString = stringValue5; + } + } + break; + case "MyInt": + { + if (configuration["MyInt"] is string stringValue6) + { + obj.MyInt = ParseInt(stringValue6, () => section.Path); + } + } + break; + case "MyList": + { + if (HasChildren(section)) + { + List temp7 = obj.MyList; + temp7 ??= new List(); + BindCore(section, ref temp7, binderOptions); + obj.MyList = temp7; + } + } + break; + case "MyArray": + { + if (HasChildren(section)) + { + int[] temp8 = obj.MyArray; + temp8 ??= new int[0]; + BindCore(section, ref temp8, binderOptions); + obj.MyArray = temp8; + } + } + break; + case "MyDictionary": + { + if (HasChildren(section)) + { + Dictionary temp9 = obj.MyDictionary; + temp9 ??= new Dictionary(); + BindCore(section, ref temp9, binderOptions); + obj.MyDictionary = temp9; + } + } + break; + default: + { + if (binderOptions?.ErrorOnUnknownConfiguration == true) + { + (temp ??= new List()).Add($"'{section.Key}'"); + } + } + break; + } + } + + if (temp is not null) + { + throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass)}: {string.Join(", ", temp)}"); + } + } + + public static bool HasValueOrChildren(IConfiguration configuration) + { + if ((configuration as IConfigurationSection)?.Value is not null) + { + return true; + } + return HasChildren(configuration); + } + + public static bool HasChildren(IConfiguration configuration) + { + foreach (IConfigurationSection section in configuration.GetChildren()) + { + return true; + } + return false; + } + + public static BinderOptions? GetBinderOptions(System.Action? configureOptions) + { + if (configureOptions is null) + { + return null; + } + BinderOptions binderOptions = new(); + configureOptions(binderOptions); + if (binderOptions.BindNonPublicProperties) + { + throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'."); + } + return binderOptions; + } + + public static int ParseInt(string stringValue, Func getPath) + { + try + { + return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture); + } + catch (Exception exception) + { + throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Get_T_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Get_T_BinderOptions.generated.txt new file mode 100644 index 00000000000000..0d5a4c3136c86f --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Get_T_BinderOptions.generated.txt @@ -0,0 +1,214 @@ +// +#nullable enable + +internal static class GeneratedConfigurationBinder +{ + public static T? Get(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Action? configureOptions) => (T?)(global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.GetCore(configuration, typeof(T), configureOptions) ?? default(T)); +} + +namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration +{ + using Microsoft.Extensions.Configuration; + using System; + using System.Collections.Generic; + using System.Globalization; + + internal static class Helpers + { + public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions) + { + if (configuration is null) + { + throw new ArgumentNullException(nameof(configuration)); + } + + BinderOptions? binderOptions = GetBinderOptions(configureOptions); + + if (!HasValueOrChildren(configuration)) + { + return null; + } + + if (type == typeof(Program.MyClass)) + { + var obj = new Program.MyClass(); + BindCore(configuration, ref obj, binderOptions); + return obj; + } + + throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input."); + } + + public static void BindCore(IConfiguration configuration, ref List obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + foreach (IConfigurationSection section in configuration.GetChildren()) + { + int element; + if (section.Value is string stringValue1) + { + element = ParseInt(stringValue1, () => section.Path); + obj.Add(element); + } + } + } + + public static void BindCore(IConfiguration configuration, ref int[] obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + var temp2 = new List(); + BindCore(configuration, ref temp2, binderOptions); + int originalCount = obj.Length; + Array.Resize(ref obj, originalCount + temp2.Count); + temp2.CopyTo(obj, originalCount); + } + + public static void BindCore(IConfiguration configuration, ref Dictionary obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + foreach (IConfigurationSection section in configuration.GetChildren()) + { + string key = section.Key; + if (section.Value is string stringValue4) + { + obj[key] = stringValue4; + } + } + } + + public static void BindCore(IConfiguration configuration, ref Program.MyClass obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + List? temp = null; + foreach (IConfigurationSection section in configuration.GetChildren()) + { + switch (section.Key) + { + case "MyString": + { + if (configuration["MyString"] is string stringValue5) + { + obj.MyString = stringValue5; + } + } + break; + case "MyInt": + { + if (configuration["MyInt"] is string stringValue6) + { + obj.MyInt = ParseInt(stringValue6, () => section.Path); + } + } + break; + case "MyList": + { + if (HasChildren(section)) + { + List temp7 = obj.MyList; + temp7 ??= new List(); + BindCore(section, ref temp7, binderOptions); + obj.MyList = temp7; + } + } + break; + case "MyArray": + { + if (HasChildren(section)) + { + int[] temp8 = obj.MyArray; + temp8 ??= new int[0]; + BindCore(section, ref temp8, binderOptions); + obj.MyArray = temp8; + } + } + break; + case "MyDictionary": + { + if (HasChildren(section)) + { + Dictionary temp9 = obj.MyDictionary; + temp9 ??= new Dictionary(); + BindCore(section, ref temp9, binderOptions); + obj.MyDictionary = temp9; + } + } + break; + default: + { + if (binderOptions?.ErrorOnUnknownConfiguration == true) + { + (temp ??= new List()).Add($"'{section.Key}'"); + } + } + break; + } + } + + if (temp is not null) + { + throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass)}: {string.Join(", ", temp)}"); + } + } + + public static bool HasValueOrChildren(IConfiguration configuration) + { + if ((configuration as IConfigurationSection)?.Value is not null) + { + return true; + } + return HasChildren(configuration); + } + + public static bool HasChildren(IConfiguration configuration) + { + foreach (IConfigurationSection section in configuration.GetChildren()) + { + return true; + } + return false; + } + + public static BinderOptions? GetBinderOptions(System.Action? configureOptions) + { + if (configureOptions is null) + { + return null; + } + BinderOptions binderOptions = new(); + configureOptions(binderOptions); + if (binderOptions.BindNonPublicProperties) + { + throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'."); + } + return binderOptions; + } + + public static int ParseInt(string stringValue, Func getPath) + { + try + { + return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture); + } + catch (Exception exception) + { + throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Get_TypeOf.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Get_TypeOf.generated.txt new file mode 100644 index 00000000000000..023bf6283e3833 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Get_TypeOf.generated.txt @@ -0,0 +1,124 @@ +// +#nullable enable + +internal static class GeneratedConfigurationBinder +{ + public static object? Get(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.GetCore(configuration, type, configureOptions: null); +} + +namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration +{ + using Microsoft.Extensions.Configuration; + using System; + using System.Collections.Generic; + using System.Globalization; + + internal static class Helpers + { + public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions) + { + if (configuration is null) + { + throw new ArgumentNullException(nameof(configuration)); + } + + BinderOptions? binderOptions = GetBinderOptions(configureOptions); + + if (!HasValueOrChildren(configuration)) + { + return null; + } + + if (type == typeof(Program.MyClass2)) + { + var obj = new Program.MyClass2(); + BindCore(configuration, ref obj, binderOptions); + return obj; + } + + throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input."); + } + + public static void BindCore(IConfiguration configuration, ref Program.MyClass2 obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + List? temp = null; + foreach (IConfigurationSection section in configuration.GetChildren()) + { + switch (section.Key) + { + case "MyInt": + { + if (configuration["MyInt"] is string stringValue1) + { + obj.MyInt = ParseInt(stringValue1, () => section.Path); + } + } + break; + default: + { + if (binderOptions?.ErrorOnUnknownConfiguration == true) + { + (temp ??= new List()).Add($"'{section.Key}'"); + } + } + break; + } + } + + if (temp is not null) + { + throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass2)}: {string.Join(", ", temp)}"); + } + } + + public static bool HasValueOrChildren(IConfiguration configuration) + { + if ((configuration as IConfigurationSection)?.Value is not null) + { + return true; + } + return HasChildren(configuration); + } + + public static bool HasChildren(IConfiguration configuration) + { + foreach (IConfigurationSection section in configuration.GetChildren()) + { + return true; + } + return false; + } + + public static BinderOptions? GetBinderOptions(System.Action? configureOptions) + { + if (configureOptions is null) + { + return null; + } + BinderOptions binderOptions = new(); + configureOptions(binderOptions); + if (binderOptions.BindNonPublicProperties) + { + throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'."); + } + return binderOptions; + } + + public static int ParseInt(string stringValue, Func getPath) + { + try + { + return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture); + } + catch (Exception exception) + { + throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Get_TypeOf_BinderOptions.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Get_TypeOf_BinderOptions.generated.txt new file mode 100644 index 00000000000000..f599117afe8a81 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Get_TypeOf_BinderOptions.generated.txt @@ -0,0 +1,124 @@ +// +#nullable enable + +internal static class GeneratedConfigurationBinder +{ + public static object? Get(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::System.Type type, global::System.Action? configureOptions) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.GetCore(configuration, type, configureOptions); +} + +namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration +{ + using Microsoft.Extensions.Configuration; + using System; + using System.Collections.Generic; + using System.Globalization; + + internal static class Helpers + { + public static object? GetCore(this IConfiguration configuration, Type type, Action? configureOptions) + { + if (configuration is null) + { + throw new ArgumentNullException(nameof(configuration)); + } + + BinderOptions? binderOptions = GetBinderOptions(configureOptions); + + if (!HasValueOrChildren(configuration)) + { + return null; + } + + if (type == typeof(Program.MyClass2)) + { + var obj = new Program.MyClass2(); + BindCore(configuration, ref obj, binderOptions); + return obj; + } + + throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input."); + } + + public static void BindCore(IConfiguration configuration, ref Program.MyClass2 obj, BinderOptions? binderOptions) + { + if (obj is null) + { + throw new ArgumentNullException(nameof(obj)); + } + + List? temp = null; + foreach (IConfigurationSection section in configuration.GetChildren()) + { + switch (section.Key) + { + case "MyInt": + { + if (configuration["MyInt"] is string stringValue1) + { + obj.MyInt = ParseInt(stringValue1, () => section.Path); + } + } + break; + default: + { + if (binderOptions?.ErrorOnUnknownConfiguration == true) + { + (temp ??= new List()).Add($"'{section.Key}'"); + } + } + break; + } + } + + if (temp is not null) + { + throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {typeof(Program.MyClass2)}: {string.Join(", ", temp)}"); + } + } + + public static bool HasValueOrChildren(IConfiguration configuration) + { + if ((configuration as IConfigurationSection)?.Value is not null) + { + return true; + } + return HasChildren(configuration); + } + + public static bool HasChildren(IConfiguration configuration) + { + foreach (IConfigurationSection section in configuration.GetChildren()) + { + return true; + } + return false; + } + + public static BinderOptions? GetBinderOptions(System.Action? configureOptions) + { + if (configureOptions is null) + { + return null; + } + BinderOptions binderOptions = new(); + configureOptions(binderOptions); + if (binderOptions.BindNonPublicProperties) + { + throw new global::System.NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'."); + } + return binderOptions; + } + + public static int ParseInt(string stringValue, Func getPath) + { + try + { + return int.Parse(stringValue, NumberStyles.Integer, CultureInfo.InvariantCulture); + } + catch (Exception exception) + { + throw new InvalidOperationException($"Failed to convert configuration value at '{getPath()}' to type '{typeof(int)}'.", exception); + } + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/TestPrimitivesGen.generated.txt b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Primitives.generated.txt similarity index 100% rename from src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/TestPrimitivesGen.generated.txt rename to src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/Baselines/Primitives.generated.txt diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBindingGeneratorTests.Baselines.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBindingGeneratorTests.Baselines.cs new file mode 100644 index 00000000000000..2ac4ea12c1dc59 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBindingGeneratorTests.Baselines.cs @@ -0,0 +1,731 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using SourceGenerators.Tests; +using Xunit; + +namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration.Tests +{ + public partial class ConfigurationBindingGeneratorTests + { + private const string BindCallSampleCode = @" +using System.Collections.Generic; +using Microsoft.Extensions.Configuration; + +public class Program +{ + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfigurationRoot config = configurationBuilder.Build(); + + MyClass configObj = new(); + config.Bind(configObj); + config.Bind(configObj, options => { }); + config.Bind(""key"", configObj); + } + + public class MyClass + { + public string MyString { get; set; } + public int MyInt { get; set; } + public List MyList { get; set; } + public Dictionary MyDictionary { get; set; } + public Dictionary MyComplexDictionary { get; set; } + } + + public class MyClass2 { } +}"; + + [Theory] + [InlineData(LanguageVersion.Preview)] + [InlineData(LanguageVersion.CSharp11)] + public async Task Bind(LanguageVersion langVersion) => + await VerifyAgainstBaselineUsingFile("Bind.generated.txt", BindCallSampleCode, langVersion); + + [Fact] + public async Task Bind_Instance() + { + string source = """ + using System.Collections.Generic; + using Microsoft.Extensions.Configuration; + + public class Program + { + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfigurationRoot config = configurationBuilder.Build(); + + MyClass configObj = new(); + config.Bind(configObj); + } + + public class MyClass + { + public string MyString { get; set; } + public int MyInt { get; set; } + public List MyList { get; set; } + public Dictionary MyDictionary { get; set; } + public Dictionary MyComplexDictionary { get; set; } + } + + public class MyClass2 { } + } + """; + + await VerifyAgainstBaselineUsingFile("Bind_Instance.generated.txt", source); + } + + [Fact] + public async Task Bind_Instance_BinderOptions() + { + string source = """ + using System.Collections.Generic; + using Microsoft.Extensions.Configuration; + + public class Program + { + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfigurationRoot config = configurationBuilder.Build(); + + MyClass configObj = new(); + config.Bind(configObj, options => { }); + } + + public class MyClass + { + public string MyString { get; set; } + public int MyInt { get; set; } + public List MyList { get; set; } + public Dictionary MyDictionary { get; set; } + public Dictionary MyComplexDictionary { get; set; } + } + + public class MyClass2 { } + } + """; + + await VerifyAgainstBaselineUsingFile("Bind_Instance_BinderOptions.generated.txt", source); + } + + [Fact] + public async Task Bind_Key_Instance() + { + string source = """ + using System.Collections.Generic; + using Microsoft.Extensions.Configuration; + + public class Program + { + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfigurationRoot config = configurationBuilder.Build(); + + MyClass configObj = new(); + config.Bind("key", configObj); + } + + public class MyClass + { + public string MyString { get; set; } + public int MyInt { get; set; } + public List MyList { get; set; } + public Dictionary MyDictionary { get; set; } + public Dictionary MyComplexDictionary { get; set; } + } + + public class MyClass2 { } + } + """; + + await VerifyAgainstBaselineUsingFile("Bind_Key_Instance.generated.txt", source); + } + + [Fact] + public async Task Get() + { + string source = @" +using System.Collections.Generic; +using Microsoft.Extensions.Configuration; + +public class Program +{ + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfigurationRoot config = configurationBuilder.Build(); + + MyClass configObj = config.Get(); + configObj = config.Get(typeof(MyClass2)); + configObj = config.Get(binderOptions => { }); + configObj = config.Get(typeof(MyClass2), binderOptions => { }); + } + + public class MyClass + { + public string MyString { get; set; } + public int MyInt { get; set; } + public List MyList { get; set; } + public int[] MyArray { get; set; } + public Dictionary MyDictionary { get; set; } + } + + public class MyClass2 + { + public int MyInt { get; set; } + } + + public class MyClass3 + { + public int MyInt { get; set; } + } + + public class MyClass4 + { + public int MyInt { get; set; } + } +}"; + + await VerifyAgainstBaselineUsingFile("Get.generated.txt", source); + } + + [Fact] + public async Task Get_T() + { + string source = """ + using System.Collections.Generic; + using Microsoft.Extensions.Configuration; + + public class Program + { + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfigurationRoot config = configurationBuilder.Build(); + + MyClass configObj = config.Get(); + } + + public class MyClass + { + public string MyString { get; set; } + public int MyInt { get; set; } + public List MyList { get; set; } + public int[] MyArray { get; set; } + public Dictionary MyDictionary { get; set; } + } + + public class MyClass2 + { + public int MyInt { get; set; } + } + + public class MyClass3 + { + public int MyInt { get; set; } + } + + public class MyClass4 + { + public int MyInt { get; set; } + } + } + """; + + await VerifyAgainstBaselineUsingFile("Get_T.generated.txt", source); + } + + [Fact] + public async Task Get_T_BinderOptions() + { + string source = """ + using System.Collections.Generic; + using Microsoft.Extensions.Configuration; + + public class Program + { + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfigurationRoot config = configurationBuilder.Build(); + + MyClass configObj = config.Get(binderOptions => { }); + } + + public class MyClass + { + public string MyString { get; set; } + public int MyInt { get; set; } + public List MyList { get; set; } + public int[] MyArray { get; set; } + public Dictionary MyDictionary { get; set; } + } + + public class MyClass2 + { + public int MyInt { get; set; } + } + + public class MyClass3 + { + public int MyInt { get; set; } + } + + public class MyClass4 + { + public int MyInt { get; set; } + } + } + """; + + await VerifyAgainstBaselineUsingFile("Get_T_BinderOptions.generated.txt", source); + } + + [Fact] + public async Task Get_TypeOf() + { + string source = """ + using System.Collections.Generic; + using Microsoft.Extensions.Configuration; + + public class Program + { + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfigurationRoot config = configurationBuilder.Build(); + + MyClass configObj = config.Get(typeof(MyClass2)); + } + + public class MyClass + { + public string MyString { get; set; } + public int MyInt { get; set; } + public List MyList { get; set; } + public int[] MyArray { get; set; } + public Dictionary MyDictionary { get; set; } + } + + public class MyClass2 + { + public int MyInt { get; set; } + } + + public class MyClass3 + { + public int MyInt { get; set; } + } + + public class MyClass4 + { + public int MyInt { get; set; } + } + } + """; + + await VerifyAgainstBaselineUsingFile("Get_TypeOf.generated.txt", source); + } + + [Fact] + public async Task Get_TypeOf_BinderOptions() + { + string source = """ + using System.Collections.Generic; + using Microsoft.Extensions.Configuration; + + public class Program + { + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfigurationRoot config = configurationBuilder.Build(); + + config.Get(typeof(MyClass2), binderOptions => { }); + } + + public class MyClass + { + public string MyString { get; set; } + public int MyInt { get; set; } + public List MyList { get; set; } + public int[] MyArray { get; set; } + public Dictionary MyDictionary { get; set; } + } + + public class MyClass2 + { + public int MyInt { get; set; } + } + + public class MyClass3 + { + public int MyInt { get; set; } + } + + public class MyClass4 + { + public int MyInt { get; set; } + } + } + """; + + await VerifyAgainstBaselineUsingFile("Get_TypeOf_BinderOptions.generated.txt", source); + } + + [Fact] + public async Task GetValue() + { + string source = @" +using System.Collections.Generic; +using System.Globalization; +using Microsoft.Extensions.Configuration; + +public class Program +{ + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfigurationRoot config = configurationBuilder.Build(); + + config.GetValue(""key""); + config.GetValue(typeof(bool?), ""key""); + config.GetValue(""key"", new MyClass()); + config.GetValue(""key"", new byte[] { }); + config.GetValue(typeof(CultureInfo), ""key"", CultureInfo.InvariantCulture); + } + + public class MyClass + { + public string MyString { get; set; } + public int MyInt { get; set; } + public List MyList { get; set; } + public int[] MyArray { get; set; } + public Dictionary MyDictionary { get; set; } + } +}"; + + await VerifyAgainstBaselineUsingFile("GetValue.generated.txt", source); + } + + [Fact] + public async Task GetValue_T_Key() + { + string source = """ + using Microsoft.Extensions.Configuration; + + public class Program + { + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfigurationRoot config = configurationBuilder.Build(); + + config.GetValue("key"); + } + } + """; + + await VerifyAgainstBaselineUsingFile("GetValue_T_Key.generated.txt", source); + } + + [Fact] + public async Task GetValue_T_Key_DefaultValue() + { + string source = """ + using System.Collections.Generic; + using System.Globalization; + using Microsoft.Extensions.Configuration; + + public class Program + { + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfigurationRoot config = configurationBuilder.Build(); + + config.GetValue("key", 5); + } + } + """; + + await VerifyAgainstBaselineUsingFile("GetValue_T_Key_DefaultValue.generated.txt", source); + } + + [Fact] + public async Task GetValue_TypeOf_Key() + { + string source = """ + using Microsoft.Extensions.Configuration; + + public class Program + { + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfigurationRoot config = configurationBuilder.Build(); + + config.GetValue(typeof(bool?), "key"); + } + } + """; + + await VerifyAgainstBaselineUsingFile("GetValue_TypeOf_Key.generated.txt", source); + } + + [Fact] + public async Task GetValue_TypeOf_Key_DefaultValue() + { + string source = """ + using System.Globalization; + using Microsoft.Extensions.Configuration; + + public class Program + { + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfigurationRoot config = configurationBuilder.Build(); + + config.GetValue(typeof(CultureInfo), "key", CultureInfo.InvariantCulture); + } + } + """; + + await VerifyAgainstBaselineUsingFile("GetValue_TypeOf_Key_DefaultValue.generated.txt", source); + } + + [Fact] + public async Task Configure() + { + string source = @" +using System.Collections.Generic; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +public class Program +{ + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfiguration config = configurationBuilder.Build(); + IConfigurationSection section = config.GetSection(""MySection""); + + ServiceCollection services = new(); + services.Configure(section); + } + + public class MyClass + { + public string MyString { get; set; } + public int MyInt { get; set; } + public List MyList { get; set; } + public List MyList2 { get; set; } + public Dictionary MyDictionary { get; set; } + } + + public class MyClass2 + { + public int MyInt { get; set; } + } +}"; + + await VerifyAgainstBaselineUsingFile("Configure.generated.txt", source); + } + + [Fact] + public async Task None() + { + string source = @" +using System.Collections.Generic; +using Microsoft.AspNetCore.Builder; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; + +public class Program +{ + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfiguration config = configurationBuilder.Build(); + IConfigurationSection section = config.GetSection(""MySection""); + } + + public class MyClass + { + public string MyString { get; set; } + public int MyInt { get; set; } + public List MyList { get; set; } + public List MyList2 { get; set; } + public Dictionary MyDictionary { get; set; } + } + + public class MyClass2 + { + public int MyInt { get; set; } + } +}" + ; + + var (d, r) = await RunGenerator(source); + Assert.Empty(r); + Assert.Empty(d); + } + + [Fact] + public async Task PrimitivesGen() + { + string source = """ + using System; + using System.Globalization; + using Microsoft.Extensions.Configuration; + + public class Program + { + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfigurationRoot config = configurationBuilder.Build(); + + MyClass obj = new(); + config.Bind(obj); + } + + public class MyClass + { + public bool Prop0 { get; set; } + public byte Prop1 { get; set; } + public sbyte Prop2 { get; set; } + public char Prop3 { get; set; } + public double Prop4 { get; set; } + public string Prop5 { get; set; } + public int Prop6 { get; set; } + public short Prop8 { get; set; } + public long Prop9 { get; set; } + public float Prop10 { get; set; } + public ushort Prop13 { get; set; } + public uint Prop14 { get; set; } + public ulong Prop15 { get; set; } + public object Prop16 { get; set; } + public CultureInfo Prop17 { get; set; } + public DateTime Prop19 { get; set; } + public DateTimeOffset Prop20 { get; set; } + public decimal Prop21 { get; set; } + public TimeSpan Prop23 { get; set; } + public Guid Prop24 { get; set; } + public Uri Prop25 { get; set; } + public Version Prop26 { get; set; } + public DayOfWeek Prop27 { get; set; } + public Int128 Prop7 { get; set; } + public Half Prop11 { get; set; } + public UInt128 Prop12 { get; set; } + public DateOnly Prop18 { get; set; } + public TimeOnly Prop22 { get; set; } + public byte[] Prop22 { get; set; } + public int Prop23 { get; set; } + public DateTime Prop24 { get; set; } + } + } + """; + + await VerifyAgainstBaselineUsingFile("Primitives.generated.txt", source); + } + + [Fact] + public async Task TestCollectionsGen() + { + string source = """ + using System.Collections.Generic; + using Microsoft.Extensions.Configuration; + + public class Program + { + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfiguration config = configurationBuilder.Build(); + IConfigurationSection section = config.GetSection(""MySection""); + + section.Get(); + } + + public class MyClassWithCustomCollections + { + public CustomDictionary CustomDictionary { get; set; } + public CustomList CustomList { get; set; } + public ICustomDictionary ICustomDictionary { get; set; } + public ICustomSet ICustomCollection { get; set; } + public IReadOnlyList IReadOnlyList { get; set; } + public IReadOnlyDictionary UnsupportedIReadOnlyDictionaryUnsupported { get; set; } + public IReadOnlyDictionary IReadOnlyDictionary { get; set; } + } + + public class CustomDictionary : Dictionary + { + } + + public class CustomList : List + { + } + + public interface ICustomDictionary : IDictionary + { + } + + public interface ICustomSet : ISet + { + } + } + """; + + await VerifyAgainstBaselineUsingFile("Collections.generated.txt", source, assessDiagnostics: (d) => + { + Assert.Equal(6, d.Length); + Test(d.Where(diagnostic => diagnostic.Id is "SYSLIB1100"), "Did not generate binding logic for a type"); + Test(d.Where(diagnostic => diagnostic.Id is "SYSLIB1101"), "Did not generate binding logic for a property on a type"); + + static void Test(IEnumerable d, string expectedTitle) + { + Assert.Equal(3, d.Count()); + foreach (Diagnostic diagnostic in d) + { + Assert.Equal(DiagnosticSeverity.Warning, diagnostic.Severity); + Assert.Contains(expectedTitle, diagnostic.Descriptor.Title.ToString(CultureInfo.InvariantCulture)); + } + } + }); + } + + private async Task VerifyAgainstBaselineUsingFile( + string filename, + string testSourceCode, + LanguageVersion languageVersion = LanguageVersion.Preview, + Action>? assessDiagnostics = null) + { + string baseline = LineEndingsHelper.Normalize(await File.ReadAllTextAsync(Path.Combine("Baselines", filename)).ConfigureAwait(false)); + string[] expectedLines = baseline.Replace("%VERSION%", typeof(ConfigurationBindingGenerator).Assembly.GetName().Version?.ToString()) + .Split(Environment.NewLine); + + var (d, r) = await RunGenerator(testSourceCode, languageVersion); + + Assert.Single(r); + (assessDiagnostics ?? ((d) => Assert.Empty(d))).Invoke(d); + + Assert.True(RoslynTestUtils.CompareLines(expectedLines, r[0].SourceText, + out string errorMessage), errorMessage); + } + } +} diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBindingGeneratorTests.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBindingGeneratorTests.cs new file mode 100644 index 00000000000000..82a2e97890afed --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBindingGeneratorTests.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. + +using System; +using System.Collections; +using System.Collections.Immutable; +using System.Globalization; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.Extensions.DependencyInjection; +using SourceGenerators.Tests; +using Xunit; + +namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration.Tests +{ + [ActiveIssue("https://github.com/dotnet/runtime/issues/52062", TestPlatforms.Browser)] + public partial class ConfigurationBindingGeneratorTests + { + [Fact] + public async Task LangVersionMustBeCharp11OrHigher() + { + var (d, r) = await RunGenerator(BindCallSampleCode, LanguageVersion.CSharp10); + Assert.Empty(r); + + Diagnostic diagnostic = Assert.Single(d); + Assert.True(diagnostic.Id == "SYSLIB1102"); + Assert.Contains("C# 11", diagnostic.Descriptor.Title.ToString(CultureInfo.InvariantCulture)); + Assert.Equal(DiagnosticSeverity.Error, diagnostic.Severity); + } + + private async Task<(ImmutableArray, ImmutableArray)> RunGenerator( + string testSourceCode, + LanguageVersion langVersion = LanguageVersion.CSharp11) => + await RoslynTestUtils.RunGenerator( + new ConfigurationBindingGenerator(), + new[] { + typeof(ConfigurationBinder).Assembly, + typeof(CultureInfo).Assembly, + typeof(IConfiguration).Assembly, + typeof(IServiceCollection).Assembly, + typeof(IDictionary).Assembly, + typeof(ServiceCollection).Assembly, + typeof(OptionsConfigurationServiceCollectionExtensions).Assembly, + typeof(Uri).Assembly, + }, + new[] { testSourceCode }, + langVersion: langVersion).ConfigureAwait(false); + } +} diff --git a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBindingSourceGeneratorTests.cs b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBindingSourceGeneratorTests.cs index 1f878cf5710b30..8296ef6b6d2dd6 100644 --- a/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBindingSourceGeneratorTests.cs +++ b/src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/ConfigurationBindingSourceGeneratorTests.cs @@ -23,6 +23,14 @@ namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration.Tests [ActiveIssue("https://github.com/dotnet/runtime/issues/52062", TestPlatforms.Browser)] public class ConfigurationBindingSourceGeneratorTests { + private static class Diagnostics + { + public static (string Id, string Title) TypeNotSupported = ("SYSLIB1100", "Did not generate binding logic for a type"); + public static (string Id, string Title) PropertyNotSupported = ("SYSLIB1101", "Did not generate binding logic for a property on a type"); + public static (string Id, string Title) ValueTypesInvalidForBind = ("SYSLIB1103", "Value types are invalid inputs to configuration 'Bind' methods"); + public static (string Id, string Title) CouldNotDetermineTypeInfo = ("SYSLIB1104", "The target type for a binder call could not be determined"); + } + private const string BindCallSampleCode = @" using System.Collections.Generic; using Microsoft.Extensions.Configuration; @@ -301,8 +309,8 @@ public interface ICustomSet : ISet await VerifyAgainstBaselineUsingFile("TestCollectionsGen.generated.txt", testSourceCode, assessDiagnostics: (d) => { Assert.Equal(6, d.Length); - Test(d.Where(diagnostic => diagnostic.Id is "SYSLIB1100"), "Did not generate binding logic for a type"); - Test(d.Where(diagnostic => diagnostic.Id is "SYSLIB1101"), "Did not generate binding logic for a property on a type"); + Test(d.Where(diagnostic => diagnostic.Id == Diagnostics.TypeNotSupported.Id), Diagnostics.TypeNotSupported.Title); + Test(d.Where(diagnostic => diagnostic.Id == Diagnostics.PropertyNotSupported.Id), Diagnostics.PropertyNotSupported.Title); static void Test(IEnumerable d, string expectedTitle) { @@ -316,6 +324,146 @@ static void Test(IEnumerable d, string expectedTitle) }); } + [Fact] + public async Task ValueTypesAreInvalidAsBindInputs() + { + string source = """ + using System; + using System.Collections.Generic; + using Microsoft.Extensions.Configuration; + + public class Program + { + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfigurationRoot config = configurationBuilder.Build(); + + int myInt = 1 + config.Bind(myInt); + int? myNInt = 2; + config.Bind(myNInt) + + var myStruct = new MyStruct() + config.Bind(myStruct, options => { }) + MyStruct? myNStruct = new(); + config.Bind(myNStruct, options => { }); + + var myRecordStruct = new MyRecordStruct(); + config.Bind("key", myRecordStruct); + MyRecordStruct? myNRecordStruct = new(); + config.Bind("key", myNRecordStruct); + + Memory memory = new(new int[] {1, 2, 3}); + config.Bind(memory); + } + + public struct MyStruct { } + public record struct MyRecordStruct { } + } + """; + + var (d, r) = await RunGenerator(source); + Assert.Empty(r); + Assert.Equal(7, d.Count()); + + foreach (Diagnostic diagnostic in d) + { + Assert.True(diagnostic.Id == Diagnostics.ValueTypesInvalidForBind.Id); + Assert.Contains(Diagnostics.ValueTypesInvalidForBind.Title, diagnostic.Descriptor.Title.ToString(CultureInfo.InvariantCulture)); + Assert.Equal(DiagnosticSeverity.Warning, diagnostic.Severity); + Assert.NotNull(diagnostic.Location); + } + } + + [Fact] + public async Task InvalidRootMethodInputTypes() + { + string source = """ + using System.Collections.Generic; + using Microsoft.Extensions.Configuration; + + public class Program + { + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfigurationRoot config = configurationBuilder.Build(); + + config.GetValue(typeof(int*), ""); + config.Get>(); + } + + public struct MyStruct { } + public record struct MyRecordStruct { } + } + """; + + var (d, r) = await RunGenerator(source); + Assert.Empty(r); + Assert.Equal(2, d.Count()); + + foreach (Diagnostic diagnostic in d) + { + Assert.True(diagnostic.Id == Diagnostics.CouldNotDetermineTypeInfo.Id); + Assert.Contains(Diagnostics.CouldNotDetermineTypeInfo.Title, diagnostic.Descriptor.Title.ToString(CultureInfo.InvariantCulture)); + Assert.Equal(DiagnosticSeverity.Warning, diagnostic.Severity); + Assert.NotNull(diagnostic.Location); + } + } + + [Fact] + public async Task CannotDetermineTypeInfo() + { + string source = """ + using Microsoft.AspNetCore.Builder; + using Microsoft.Extensions.Configuration; + using Microsoft.Extensions.DependencyInjection; + + public class Program + { + public static void Main() + { + ConfigurationBuilder configurationBuilder = new(); + IConfiguration config = configurationBuilder.Build(); + + PerformGenericBinderCalls(config); + } + + public static void PerformGenericBinderCalls(IConfiguration config) where T : class + { + config.Get(); + config.Get(binderOptions => { }); + config.GetValue("key"); + config.GetValue("key", default(T)); + + IConfigurationSection section = config.GetSection("MySection"); + ServiceCollection services = new(); + services.Configure(section); + } + + private void BindOptions(IConfiguration config, object? instance) + { + config.Bind(instance); + } + + public class MyClass { } + } + """; + + var (d, r) = await RunGenerator(source); + Assert.Empty(r); + Assert.Equal(5, d.Count()); + + foreach (Diagnostic diagnostic in d) + { + Assert.True(diagnostic.Id == Diagnostics.CouldNotDetermineTypeInfo.Id); + Assert.Contains(Diagnostics.CouldNotDetermineTypeInfo.Title, diagnostic.Descriptor.Title.ToString(CultureInfo.InvariantCulture)); + Assert.Equal(DiagnosticSeverity.Warning, diagnostic.Severity); + Assert.NotNull(diagnostic.Location); + } + } + private async Task VerifyAgainstBaselineUsingFile( string filename, string testSourceCode, 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 9eb0e60f928cd6..4485cfb1402c70 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 @@ -2,10 +2,9 @@ $(NetCoreAppCurrent);$(NetFrameworkMinimum) true - true $(DefineConstants);BUILDING_SOURCE_GENERATOR_TESTS;ROSLYN4_0_OR_GREATER;ROSLYN4_4_OR_GREATER - - SYSLIB1100,SYSLIB1101 + + SYSLIB1100,SYSLIB1101,SYSLIB1103,SYSLIB1104 true @@ -16,6 +15,7 @@ + @@ -23,7 +23,6 @@ - @@ -38,10 +37,13 @@ - + PreserveNewest + + + diff --git a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationProvider.cs b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationProvider.cs index 9fbeded4fc3de6..bd357aa14c8c50 100644 --- a/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationProvider.cs +++ b/src/libraries/Microsoft.Extensions.Configuration/src/ConfigurationProvider.cs @@ -121,6 +121,6 @@ protected void OnReload() /// Generates a string representing this provider name and relevant details. /// /// The configuration name. - public override string ToString() => $"{GetType().Name}"; + public override string ToString() => GetType().Name; } } diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/CompatibilitySuppressions.xml index dd190ecbdbe9cf..c4c68039b773fb 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/CompatibilitySuppressions.xml +++ b/src/libraries/Microsoft.Extensions.DependencyInjection.Specification.Tests/src/CompatibilitySuppressions.xml @@ -1,17 +1,6 @@  + - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.Specification.ClassWithOptionalArgsCtorWithStructs.#ctor(System.DateTime,System.DateTime,System.TimeSpan,System.TimeSpan,System.DateTimeOffset,System.DateTimeOffset,System.Guid,System.Guid,Microsoft.Extensions.DependencyInjection.Specification.ClassWithOptionalArgsCtorWithStructs.CustomStruct,Microsoft.Extensions.DependencyInjection.Specification.ClassWithOptionalArgsCtorWithStructs.CustomStruct,System.Nullable{System.ConsoleColor},System.Nullable{System.ConsoleColor},System.Nullable{System.Int32},System.Nullable{System.Int32}) - true - - - - CP0002 - M:Microsoft.Extensions.DependencyInjection.Specification.DependencyInjectionSpecificationTests.ExplictServiceRegisterationWithIsService - true - CP0002 diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Extensions.DependencyInjection/src/CompatibilitySuppressions.xml new file mode 100644 index 00000000000000..42539183a5a05d --- /dev/null +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/CompatibilitySuppressions.xml @@ -0,0 +1,33 @@ + + + + + + CP0014 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(Microsoft.Extensions.DependencyInjection.IServiceCollection,Microsoft.Extensions.DependencyInjection.ServiceProviderOptions):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/Microsoft.Extensions.DependencyInjection.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.dll + true + + + CP0014 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(Microsoft.Extensions.DependencyInjection.IServiceCollection,System.Boolean):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/Microsoft.Extensions.DependencyInjection.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.dll + true + + + CP0014 + M:Microsoft.Extensions.DependencyInjection.ServiceCollectionContainerBuilderExtensions.BuildServiceProvider(Microsoft.Extensions.DependencyInjection.IServiceCollection):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/Microsoft.Extensions.DependencyInjection.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.dll + true + + + CP0014 + T:Microsoft.Extensions.DependencyInjection.DefaultServiceProviderFactory:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/Microsoft.Extensions.DependencyInjection.dll + lib/net7.0/Microsoft.Extensions.DependencyInjection.dll + true + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextPaths.cs b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextPaths.cs index 3454571b0bb737..4d056a25bd76c0 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextPaths.cs +++ b/src/libraries/Microsoft.Extensions.DependencyModel/src/DependencyContextPaths.cs @@ -20,6 +20,8 @@ internal sealed class DependencyContextPaths public IEnumerable NonApplicationPaths { get; } + private static readonly char[] s_semicolon = new[] { ';' }; + public DependencyContextPaths( string? application, string? sharedRuntime, @@ -40,7 +42,7 @@ private static DependencyContextPaths GetCurrent() internal static DependencyContextPaths Create(string? depsFiles, string? sharedRuntime) { - string[]? files = depsFiles?.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + string[]? files = depsFiles?.Split(s_semicolon, StringSplitOptions.RemoveEmptyEntries); string? application = files != null && files.Length > 0 ? files[0] : null; string[]? nonApplicationPaths = files? diff --git a/src/libraries/Microsoft.Extensions.DependencyModel/tests/Microsoft.Extensions.DependencyModel.Tests.csproj b/src/libraries/Microsoft.Extensions.DependencyModel/tests/Microsoft.Extensions.DependencyModel.Tests.csproj index f6e4a1bbea159b..da448526ca8df9 100644 --- a/src/libraries/Microsoft.Extensions.DependencyModel/tests/Microsoft.Extensions.DependencyModel.Tests.csproj +++ b/src/libraries/Microsoft.Extensions.DependencyModel/tests/Microsoft.Extensions.DependencyModel.Tests.csproj @@ -6,6 +6,9 @@ $(DefaultItemExcludes);nonentrypointassembly\* true + + + $(NoWarn);IL3054 diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Extensions.Hosting/src/CompatibilitySuppressions.xml new file mode 100644 index 00000000000000..bcbbda259455e9 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Hosting/src/CompatibilitySuppressions.xml @@ -0,0 +1,82 @@ + + + + + + CP0014 + M:Microsoft.Extensions.Hosting.Host.CreateApplicationBuilder:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/Microsoft.Extensions.Hosting.dll + lib/net7.0/Microsoft.Extensions.Hosting.dll + true + + + CP0014 + M:Microsoft.Extensions.Hosting.Host.CreateApplicationBuilder(System.String[]):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/Microsoft.Extensions.Hosting.dll + lib/net7.0/Microsoft.Extensions.Hosting.dll + true + + + CP0014 + M:Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/Microsoft.Extensions.Hosting.dll + lib/net7.0/Microsoft.Extensions.Hosting.dll + true + + + CP0014 + M:Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder(System.String[]):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/Microsoft.Extensions.Hosting.dll + lib/net7.0/Microsoft.Extensions.Hosting.dll + true + + + CP0014 + M:Microsoft.Extensions.Hosting.HostApplicationBuilder.#ctor:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/Microsoft.Extensions.Hosting.dll + lib/net7.0/Microsoft.Extensions.Hosting.dll + true + + + CP0014 + M:Microsoft.Extensions.Hosting.HostApplicationBuilder.#ctor(Microsoft.Extensions.Hosting.HostApplicationBuilderSettings):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/Microsoft.Extensions.Hosting.dll + lib/net7.0/Microsoft.Extensions.Hosting.dll + true + + + CP0014 + M:Microsoft.Extensions.Hosting.HostApplicationBuilder.#ctor(System.String[]):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/Microsoft.Extensions.Hosting.dll + lib/net7.0/Microsoft.Extensions.Hosting.dll + true + + + CP0014 + M:Microsoft.Extensions.Hosting.HostBuilder.#ctor:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/Microsoft.Extensions.Hosting.dll + lib/net7.0/Microsoft.Extensions.Hosting.dll + true + + + CP0014 + M:Microsoft.Extensions.Hosting.HostingHostBuilderExtensions.ConfigureDefaults(Microsoft.Extensions.Hosting.IHostBuilder,System.String[]):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/Microsoft.Extensions.Hosting.dll + lib/net7.0/Microsoft.Extensions.Hosting.dll + true + + + CP0014 + M:Microsoft.Extensions.Hosting.HostingHostBuilderExtensions.UseDefaultServiceProvider(Microsoft.Extensions.Hosting.IHostBuilder,System.Action{Microsoft.Extensions.DependencyInjection.ServiceProviderOptions}):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/Microsoft.Extensions.Hosting.dll + lib/net7.0/Microsoft.Extensions.Hosting.dll + true + + + CP0014 + M:Microsoft.Extensions.Hosting.HostingHostBuilderExtensions.UseDefaultServiceProvider(Microsoft.Extensions.Hosting.IHostBuilder,System.Action{Microsoft.Extensions.Hosting.HostBuilderContext,Microsoft.Extensions.DependencyInjection.ServiceProviderOptions}):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/Microsoft.Extensions.Hosting.dll + lib/net7.0/Microsoft.Extensions.Hosting.dll + true + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs index c9bc8c5c0aaaf4..fb2705c80319ba 100644 --- a/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs +++ b/src/libraries/Microsoft.Extensions.Logging.EventSource/src/LoggingEventSource.cs @@ -117,6 +117,8 @@ public static class Keywords private const string UseAppFilters = "UseAppFilters"; private const string WriteEventCoreSuppressionJustification = "WriteEventCore is safe when eventData object is a primitive type which is in this case."; private const string WriteEventDynamicDependencySuppressionJustification = "DynamicDependency attribute will ensure that the required properties are not trimmed."; + private static readonly char[] s_semicolon = new[] { ';' }; + private static readonly char[] s_colon = new[] { ':' }; private LoggingEventSource() : base(EventSourceSettings.EtwSelfDescribingEventFormat) { @@ -366,7 +368,7 @@ private static LoggerFilterRule[] ParseFilterSpec(string? filterSpec, LogLevel d var rules = new List(); int ruleStringsStartIndex = 0; - string[] ruleStrings = filterSpec.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + string[] ruleStrings = filterSpec.Split(s_semicolon, StringSplitOptions.RemoveEmptyEntries); if (ruleStrings.Length > 0 && ruleStrings[0].Equals(UseAppFilters, StringComparison.OrdinalIgnoreCase)) { // Avoid adding default rule to disable event source loggers @@ -381,7 +383,7 @@ private static LoggerFilterRule[] ParseFilterSpec(string? filterSpec, LogLevel d { string rule = ruleStrings[i]; LogLevel level = defaultLevel; - string[] parts = rule.Split(new[] { ':' }, 2); + string[] parts = rule.Split(s_colon, 2); string loggerName = parts[0]; if (loggerName.Length == 0) { diff --git a/src/libraries/Microsoft.Extensions.Logging/src/CompatibilitySuppressions.xml b/src/libraries/Microsoft.Extensions.Logging/src/CompatibilitySuppressions.xml new file mode 100644 index 00000000000000..905e8996075b11 --- /dev/null +++ b/src/libraries/Microsoft.Extensions.Logging/src/CompatibilitySuppressions.xml @@ -0,0 +1,12 @@ + + + + + + CP0014 + M:Microsoft.Extensions.Logging.LoggerFactory.Create(System.Action{Microsoft.Extensions.Logging.ILoggingBuilder}):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/Microsoft.Extensions.Logging.dll + lib/net7.0/Microsoft.Extensions.Logging.dll + true + + \ No newline at end of file diff --git a/src/libraries/Microsoft.Extensions.Logging/src/Microsoft.Extensions.Logging.csproj b/src/libraries/Microsoft.Extensions.Logging/src/Microsoft.Extensions.Logging.csproj index cb2f4264afdf99..663564ae659fd4 100644 --- a/src/libraries/Microsoft.Extensions.Logging/src/Microsoft.Extensions.Logging.csproj +++ b/src/libraries/Microsoft.Extensions.Logging/src/Microsoft.Extensions.Logging.csproj @@ -20,7 +20,6 @@ - diff --git a/src/libraries/System.Configuration.ConfigurationManager/src/CompatibilitySuppressions.xml b/src/libraries/System.Configuration.ConfigurationManager/src/CompatibilitySuppressions.xml index 7a150462088b38..cd36ac7c23bc82 100644 --- a/src/libraries/System.Configuration.ConfigurationManager/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Configuration.ConfigurationManager/src/CompatibilitySuppressions.xml @@ -1,4 +1,5 @@  + CP0002 @@ -42,6 +43,91 @@ lib/netstandard2.0/System.Configuration.ConfigurationManager.dll lib/net462/System.Configuration.ConfigurationManager.dll + + + CP0014 + F:System.Configuration.SettingsSerializeAs.Binary:[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + true + + + CP0014 + M:System.Configuration.ConfigurationException.#ctor:[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + true + + + CP0014 + M:System.Configuration.ConfigurationException.#ctor(System.String,System.Exception,System.String,System.Int32):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + true + + + CP0014 + M:System.Configuration.ConfigurationException.#ctor(System.String,System.Exception,System.Xml.XmlNode):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + true + + + CP0014 + M:System.Configuration.ConfigurationException.#ctor(System.String,System.Exception):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + true + + + CP0014 + M:System.Configuration.ConfigurationException.#ctor(System.String,System.String,System.Int32):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + true + + + CP0014 + M:System.Configuration.ConfigurationException.#ctor(System.String,System.Xml.XmlNode):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + true + + + CP0014 + M:System.Configuration.ConfigurationException.#ctor(System.String):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + true + + + CP0014 + M:System.Configuration.ConfigurationException.GetXmlNodeFilename(System.Xml.XmlNode):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + true + + + CP0014 + M:System.Configuration.ConfigurationException.GetXmlNodeLineNumber(System.Xml.XmlNode):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + true + + + CP0014 + M:System.Configuration.ConfigurationSettings.GetConfig(System.String):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + true + + + CP0014 + P:System.Configuration.ConfigurationSettings.AppSettings:[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + lib/netstandard2.0/System.Configuration.ConfigurationManager.dll + true + CP0015 M:System.Configuration.ConfigurationException.#ctor:[T:System.ObsoleteAttribute] @@ -108,4 +194,4 @@ lib/netstandard2.0/System.Configuration.ConfigurationManager.dll lib/net462/System.Configuration.ConfigurationManager.dll - \ No newline at end of file + diff --git a/src/libraries/System.Data.Common/src/System/Data/XDRSchema.cs b/src/libraries/System.Data.Common/src/System/Data/XDRSchema.cs index 33648f8d5ecbf9..4bfb8d89f63941 100644 --- a/src/libraries/System.Data.Common/src/System/Data/XDRSchema.cs +++ b/src/libraries/System.Data.Common/src/System/Data/XDRSchema.cs @@ -496,11 +496,7 @@ internal static void GetMinMax(XmlElement elNode, ref int minOccurs, ref int max string occurs = elNode.GetAttribute(Keywords.MINOCCURS); if (occurs != null && occurs.Length > 0) { - try - { - minOccurs = int.Parse(occurs, CultureInfo.InvariantCulture); - } - catch (Exception e) when (ADP.IsCatchableExceptionType(e)) + if (!int.TryParse(occurs, CultureInfo.InvariantCulture, out minOccurs)) { throw ExceptionBuilder.AttributeValues(nameof(minOccurs), "0", "1"); } @@ -514,20 +510,9 @@ internal static void GetMinMax(XmlElement elNode, ref int minOccurs, ref int max { maxOccurs = -1; } - else + else if (!int.TryParse(occurs, CultureInfo.InvariantCulture, out maxOccurs) || maxOccurs != 1) { - try - { - maxOccurs = int.Parse(occurs, CultureInfo.InvariantCulture); - } - catch (Exception e) when (ADP.IsCatchableExceptionType(e)) - { - throw ExceptionBuilder.AttributeValues(nameof(maxOccurs), "1", Keywords.STAR); - } - if (maxOccurs != 1) - { - throw ExceptionBuilder.AttributeValues(nameof(maxOccurs), "1", Keywords.STAR); - } + throw ExceptionBuilder.AttributeValues(nameof(maxOccurs), "1", Keywords.STAR); } } } diff --git a/src/libraries/System.Data.OleDb/src/OleDbCommandBuilder.cs b/src/libraries/System.Data.OleDb/src/OleDbCommandBuilder.cs index ae0930b21a88b9..376e554bda69e0 100644 --- a/src/libraries/System.Data.OleDb/src/OleDbCommandBuilder.cs +++ b/src/libraries/System.Data.OleDb/src/OleDbCommandBuilder.cs @@ -33,6 +33,8 @@ public OleDbCommandBuilder(OleDbDataAdapter? adapter) : this() } } + private static readonly char[] s_trimChars = new char[] { '@', ' ', ':' }; + private void OleDbRowUpdatingHandler(object sender, OleDbRowUpdatingEventArgs ruevent) { RowUpdatingHandler(ruevent); @@ -235,7 +237,7 @@ private static OleDbParameter[] DeriveParametersFromStoredProcedure(OleDbConnect if ((null != parameterName) && !dataRow.IsNull(parameterName, DataRowVersion.Default)) { // $CONSIDER - not trimming the @ from the beginning but to left the designer do that - parameter.ParameterName = Convert.ToString(dataRow[parameterName, DataRowVersion.Default], CultureInfo.InvariantCulture)!.TrimStart(new char[] { '@', ' ', ':' }); + parameter.ParameterName = Convert.ToString(dataRow[parameterName, DataRowVersion.Default], CultureInfo.InvariantCulture)!.TrimStart(s_trimChars); } if ((null != parameterDirection) && !dataRow.IsNull(parameterDirection, DataRowVersion.Default)) { diff --git a/src/libraries/System.Data.OleDb/src/OleDbConnectionInternal.cs b/src/libraries/System.Data.OleDb/src/OleDbConnectionInternal.cs index 7578d69bb5f57d..01745446f6b11c 100644 --- a/src/libraries/System.Data.OleDb/src/OleDbConnectionInternal.cs +++ b/src/libraries/System.Data.OleDb/src/OleDbConnectionInternal.cs @@ -175,6 +175,8 @@ public override string ServerVersion } } + internal static readonly char[] s_comma = new char[] { ',' }; + // grouping the native OLE DB casts togther by required interfaces and optional interfaces, connection then session // want these to be methods, not properties otherwise they appear in VS7 managed debugger which attempts to evaluate them @@ -475,7 +477,7 @@ internal bool AddInfoKeywordsToTable(DataTable table, DataColumn keyword) if (null != keywords) { - string[] values = keywords.Split(new char[1] { ',' }); + string[] values = keywords.Split(s_comma); for (int i = 0; i < values.Length; ++i) { DataRow row = table.NewRow(); diff --git a/src/libraries/System.Data.OleDb/src/OleDbConnectionStringBuilder.cs b/src/libraries/System.Data.OleDb/src/OleDbConnectionStringBuilder.cs index 3e5c58141d3ec8..06a1321f4c981c 100644 --- a/src/libraries/System.Data.OleDb/src/OleDbConnectionStringBuilder.cs +++ b/src/libraries/System.Data.OleDb/src/OleDbConnectionStringBuilder.cs @@ -629,7 +629,7 @@ public override bool CanConvertFrom(ITypeDescriptorContext? context, Type source if (svalue.IndexOf(',') != -1) { int convertedValue = 0; - string[] values = svalue.Split(new char[] { ',' }); + string[] values = svalue.Split(OleDbConnectionInternal.s_comma); foreach (string v in values) { convertedValue |= (int)Enum.Parse(v, true); diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/CompatibilitySuppressions.xml b/src/libraries/System.Diagnostics.DiagnosticSource/src/CompatibilitySuppressions.xml new file mode 100644 index 00000000000000..240aff3d5b7cad --- /dev/null +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/CompatibilitySuppressions.xml @@ -0,0 +1,33 @@ + + + + + + CP0014 + M:System.Diagnostics.DiagnosticListener.Write(System.String,System.Object):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/System.Diagnostics.DiagnosticSource.dll + lib/net7.0/System.Diagnostics.DiagnosticSource.dll + true + + + CP0014 + M:System.Diagnostics.DiagnosticSource.StartActivity(System.Diagnostics.Activity,System.Object):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/System.Diagnostics.DiagnosticSource.dll + lib/net7.0/System.Diagnostics.DiagnosticSource.dll + true + + + CP0014 + M:System.Diagnostics.DiagnosticSource.StopActivity(System.Diagnostics.Activity,System.Object):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/System.Diagnostics.DiagnosticSource.dll + lib/net7.0/System.Diagnostics.DiagnosticSource.dll + true + + + CP0014 + M:System.Diagnostics.DiagnosticSource.Write(System.String,System.Object):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/System.Diagnostics.DiagnosticSource.dll + lib/net7.0/System.Diagnostics.DiagnosticSource.dll + true + + \ No newline at end of file diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/AsyncStreamReader.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/AsyncStreamReader.cs index 7205722a9312ec..fbfd3a6baaae8a 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/AsyncStreamReader.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/AsyncStreamReader.cs @@ -72,7 +72,7 @@ internal void BeginReadLine() if (_sb == null) { _sb = new StringBuilder(DefaultBufferSize); - _readToBufferTask = Task.Run((Func)ReadBufferAsync); + _readToBufferTask = ReadBufferAsync(); } else { @@ -88,6 +88,8 @@ internal void CancelOperation() // This is the async callback function. Only one thread could/should call this. private async Task ReadBufferAsync() { + await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); + while (true) { try diff --git a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessWaitState.Unix.cs b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessWaitState.Unix.cs index e2d7771fe431e6..80b5f6529dc449 100644 --- a/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessWaitState.Unix.cs +++ b/src/libraries/System.Diagnostics.Process/src/System/Diagnostics/ProcessWaitState.Unix.cs @@ -532,12 +532,8 @@ private Task WaitForExitAsync(CancellationToken cancellationToken = default) } // Wait - try - { - await Task.Delay(pollingIntervalMs, cancellationToken).ConfigureAwait(false); - pollingIntervalMs = Math.Min(pollingIntervalMs * 2, MaxPollingIntervalMs); - } - catch (OperationCanceledException) { } + await Task.Delay(pollingIntervalMs, cancellationToken).ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing); + pollingIntervalMs = Math.Min(pollingIntervalMs * 2, MaxPollingIntervalMs); } } finally diff --git a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx.cs b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx.cs index eef2f1020899d6..503ce5eb3a62ab 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx.cs +++ b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx.cs @@ -494,7 +494,7 @@ private static void SetCannotChangePasswordStatus(Principal ap, bool userCannotC // even before we call ObjectSecurity to see if it would return null, because once ObjectSecurity returns null the // first time, it'll keep returning null even if we refresh the cache. if (!de.Properties.Contains("nTSecurityDescriptor")) - de.RefreshCache(new string[] { "nTSecurityDescriptor" }); + de.RefreshCache(s_nTSecurityDescriptor); ActiveDirectorySecurity adsSecurity = de.ObjectSecurity; bool denySelfFound; @@ -829,7 +829,7 @@ internal override bool IsLockedOut(AuthenticablePrincipal p) DirectoryEntry de = (DirectoryEntry)p.UnderlyingObject; Debug.Assert(de != null); - de.RefreshCache(new string[] { "msDS-User-Account-Control-Computed", "lockoutTime" }); + de.RefreshCache(s_msDSUACCLockoutTime); if (de.Properties["msDS-User-Account-Control-Computed"].Count > 0) { @@ -992,31 +992,31 @@ protected void WriteAttribute(Principal p, string attribute, T value) internal override ResultSet FindByLockoutTime( DateTime dt, MatchType matchType, Type principalType) { - return FindByDate(principalType, new string[] { "lockoutTime" }, matchType, dt); + return FindByDate(principalType, s_lockoutTime, matchType, dt); } internal override ResultSet FindByLogonTime( DateTime dt, MatchType matchType, Type principalType) { - return FindByDate(principalType, new string[] { "lastLogon", "lastLogonTimestamp" }, matchType, dt); + return FindByDate(principalType, s_lastLogonTime, matchType, dt); } internal override ResultSet FindByPasswordSetTime( DateTime dt, MatchType matchType, Type principalType) { - return FindByDate(principalType, new string[] { "pwdLastSet" }, matchType, dt); + return FindByDate(principalType, s_pwdLastSet, matchType, dt); } internal override ResultSet FindByBadPasswordAttempt( DateTime dt, MatchType matchType, Type principalType) { - return FindByDate(principalType, new string[] { "badPasswordTime" }, matchType, dt); + return FindByDate(principalType, s_badPasswordTime, matchType, dt); } internal override ResultSet FindByExpirationTime( DateTime dt, MatchType matchType, Type principalType) { - return FindByDate(principalType, new string[] { "accountExpires" }, matchType, dt); + return FindByDate(principalType, s_accountExpires, matchType, dt); } private ADEntriesSet FindByDate(Type subtype, string[] ldapAttributes, MatchType matchType, DateTime value) @@ -1300,7 +1300,7 @@ internal override ResultSet GetGroupsMemberOf(Principal p) GlobalDebug.WriteLineIf(GlobalDebug.Info, "ADStoreCtx", "GetGroupsMemberOf: principalDN={0}", principalDN); - principalDE.RefreshCache(new string[] { "memberOf", "primaryGroupID" }); + principalDE.RefreshCache(s_memberOfPrimaryGroupId); if ((principalDE.Properties["primaryGroupID"].Count > 0) && (principalDE.Properties["objectSid"].Count > 0)) @@ -2386,6 +2386,16 @@ private ulong LockoutDuration protected string contextBasePartitionDN; //contains the DN of the Partition to which the user supplied context base (this.ctxBase) belongs. protected string dnsHostName; protected ulong lockoutDuration; + private static readonly string[] s_lockoutTime = new string[] { "lockoutTime" }; + private static readonly string[] s_lastLogonTime = new string[] { "lastLogon", "lastLogonTimestamp" }; + private static readonly string[] s_pwdLastSet = new string[] { "pwdLastSet" }; + private static readonly string[] s_badPasswordTime = new string[] { "badPasswordTime" }; + private static readonly string[] s_accountExpires = new string[] { "accountExpires" }; + private static readonly string[] s_nTSecurityDescriptor = new string[] { "nTSecurityDescriptor" }; + private static readonly string[] s_msDSUACCLockoutTime = new string[] { "msDS-User-Account-Control-Computed", "lockoutTime" }; + private static readonly string[] s_memberOfPrimaryGroupId = new string[] { "memberOf", "primaryGroupID" }; + private static readonly string[] s_lockoutDuration = new string[] { "lockoutDuration" }; + internal static readonly char[] s_comma = new char[] { ',' }; protected enum StoreCapabilityMap { @@ -2415,7 +2425,7 @@ protected virtual void LoadDomainInfo() this.contextBasePartitionDN = this.defaultNamingContext; // Split the naming context's DN into its RDNs - string[] ncComponents = defaultNamingContext.Split(new char[] { ',' }); + string[] ncComponents = defaultNamingContext.Split(s_comma); StringBuilder sb = new StringBuilder(); @@ -2492,7 +2502,7 @@ protected virtual void LoadDomainInfo() this.authTypes); // So we don't load every property - domainNC.RefreshCache(new string[] { "lockoutDuration" }); + domainNC.RefreshCache(s_lockoutDuration); if (domainNC.Properties["lockoutDuration"].Count > 0) { diff --git a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx_LoadStore.cs b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx_LoadStore.cs index 5f6e60cc1b79e5..d507dd9ca28a49 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx_LoadStore.cs +++ b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/ADStoreCtx_LoadStore.cs @@ -904,7 +904,7 @@ protected static void CommaStringFromLdapConverter(dSPropertyCollection properti Debug.Assert(values[0] is string); string commaSeparatedValues = (string)values[0]; - string[] individualValues = commaSeparatedValues.Split(new char[] { ',' }); + string[] individualValues = commaSeparatedValues.Split(s_comma); // ValueCollection is Load'ed from a List List list = new List(individualValues.Length); @@ -1078,7 +1078,7 @@ protected static bool CannotChangePwdFromLdapConverter(DirectoryEntry de) // first time, it'll keep returning null even if we refresh the cache. if (!de.Properties.Contains("nTSecurityDescriptor")) - de.RefreshCache(new string[] { "nTSecurityDescriptor" }); + de.RefreshCache(s_nTSecurityDescriptor); ActiveDirectorySecurity adsSecurity = de.ObjectSecurity; @@ -1637,6 +1637,8 @@ protected static void UpdateGroupMembership(Principal group, DirectoryEntry de, } } + private static readonly string[] s_objectSid = new string[] { "objectSid" }; + // Builds a SID dn for the principal protected static string GetSidPathFromPrincipal(Principal p) { @@ -1661,7 +1663,7 @@ protected static string GetSidPathFromPrincipal(Principal p) // Force it to load if it hasn't been already loaded if (!de.Properties.Contains("objectSid")) - de.RefreshCache(new string[] { "objectSid" }); + de.RefreshCache(s_objectSid); byte[] sid = (byte[])de.Properties["objectSid"].Value; diff --git a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/SDSUtils.cs b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/SDSUtils.cs index f0e567298d6851..59d4ac4b5623fb 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/SDSUtils.cs +++ b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/AD/SDSUtils.cs @@ -780,7 +780,7 @@ internal static bool IsObjectFromGC(string path) internal static string ConstructDnsDomainNameFromDn(string dn) { // Split the DN into its RDNs - string[] ncComponents = dn.Split(new char[] { ',' }); + string[] ncComponents = dn.Split(ADStoreCtx.s_comma); StringBuilder sb = new StringBuilder(); diff --git a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Group.cs b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Group.cs index 589400d06b11fa..cc8ad3ef948321 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Group.cs +++ b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/Group.cs @@ -348,6 +348,8 @@ internal override void ResetAllChangeStatus() /// internal SearchResult SmallGroupMemberSearchResult { get; private set; } + private static readonly string[] s_member = new string[] { "member" }; + /// /// Finds if the group is "small", meaning that it has less than MaxValRange values (usually 1500) /// The property list for the searcher of a group has "member" attribute. if there are more results than MaxValRange, there will also be a "member;range=..." attribute @@ -366,7 +368,7 @@ internal bool IsSmallGroup() Debug.Assert(de != null); if (de != null) { - using (DirectorySearcher ds = new DirectorySearcher(de, "(objectClass=*)", new string[] { "member" }, SearchScope.Base)) + using (DirectorySearcher ds = new DirectorySearcher(de, "(objectClass=*)", s_member, SearchScope.Base)) { SearchResult sr = ds.FindOne(); if (sr != null) diff --git a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMUtils.cs b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMUtils.cs index 1ce1cafc5ed16b..cfbb088fe283bd 100644 --- a/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMUtils.cs +++ b/src/libraries/System.DirectoryServices.AccountManagement/src/System/DirectoryServices/AccountManagement/SAM/SAMUtils.cs @@ -18,6 +18,8 @@ internal static bool IsOfObjectClass(DirectoryEntry de, string classToCompare) return string.Equals(de.SchemaClassName, classToCompare, StringComparison.OrdinalIgnoreCase); } + internal static readonly char[] s_dot = new char[] { '.' }; + internal static bool GetOSVersion(DirectoryEntry computerDE, out int versionMajor, out int versionMinor) { Debug.Assert(SAMUtils.IsOfObjectClass(computerDE, "Computer")); @@ -56,7 +58,7 @@ internal static bool GetOSVersion(DirectoryEntry computerDE, out int versionMajo // // We'll split the string into its period-separated components, and parse // each component into an int. - string[] versionComponents = version.Split(new char[] { '.' }); + string[] versionComponents = version.Split(s_dot); Debug.Assert(versionComponents.Length >= 1); // since version was a non-empty string diff --git a/src/libraries/System.DirectoryServices/src/CompatibilitySuppressions.xml b/src/libraries/System.DirectoryServices/src/CompatibilitySuppressions.xml index d1d3de69d38dea..1d3a5528bf97a5 100644 --- a/src/libraries/System.DirectoryServices/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.DirectoryServices/src/CompatibilitySuppressions.xml @@ -1,29 +1,11 @@  + - CP0001 - T:System.DirectoryServices.DirectoryServicesPermission + CP0015 + T:System.DirectoryServices.DirectoryEntry:[T:System.ComponentModel.TypeConverterAttribute] true - - CP0001 - T:System.DirectoryServices.DirectoryServicesPermissionAccess - true - - - CP0001 - T:System.DirectoryServices.DirectoryServicesPermissionAttribute - true - - - CP0001 - T:System.DirectoryServices.DirectoryServicesPermissionEntry - true - - - CP0001 - T:System.DirectoryServices.DirectoryServicesPermissionEntryCollection - true - - + \ No newline at end of file diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ADAMInstance.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ADAMInstance.cs index 84980cff39da77..298a1276425b86 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ADAMInstance.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ADAMInstance.cs @@ -27,6 +27,7 @@ public class AdamInstance : DirectoryServer private IntPtr _authIdentity = IntPtr.Zero; private SyncUpdateCallback? _userDelegate; private readonly SyncReplicaFromAllServersCallback _syncAllFunctionPointer; + private static readonly char[] s_comma = new char[] { ',' }; #region constructors internal AdamInstance(DirectoryContext context, string adamInstanceName) @@ -707,7 +708,7 @@ internal string SiteObjectName // get the site object name from the server object name // CN=server1,CN=Servers,CN=Site1,CN=Sites // the site object name is the third component onwards - string[] components = ServerObjectName.Split(new char[] { ',' }); + string[] components = ServerObjectName.Split(s_comma); if (components.GetLength(0) < 3) { // should not happen diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectoryInterSiteTransport.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectoryInterSiteTransport.cs index 1531ed1c22fe2f..adb8b753c900ea 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectoryInterSiteTransport.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectoryInterSiteTransport.cs @@ -74,7 +74,7 @@ public static ActiveDirectoryInterSiteTransport FindByTransportType(DirectoryCon try { - de.RefreshCache(new string[] { "options" }); + de.RefreshCache(s_options); } catch (COMException e) { @@ -223,7 +223,7 @@ public ReadOnlySiteLinkCollection SiteLinks ADSearcher adSearcher = new ADSearcher(_cachedEntry, "(&(objectClass=siteLink)(objectCategory=SiteLink))", - new string[] { "cn" }, + s_cn, SearchScope.OneLevel); SearchResultCollection? results = null; @@ -271,7 +271,7 @@ public ReadOnlySiteLinkBridgeCollection SiteLinkBridges ADSearcher adSearcher = new ADSearcher(_cachedEntry, "(&(objectClass=siteLinkBridge)(objectCategory=SiteLinkBridge))", - new string[] { "cn" }, + s_cn, SearchScope.OneLevel); SearchResultCollection? results = null; @@ -307,6 +307,9 @@ public ReadOnlySiteLinkBridgeCollection SiteLinkBridges } } + private static readonly string[] s_options = new string[] { "options" }; + private static readonly string[] s_cn = new string[] { "cn" }; + public void Save() { if (_disposed) diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySite.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySite.cs index 4a1a3d1b08998c..93e8c03a2508b4 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySite.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySite.cs @@ -91,7 +91,7 @@ public static ActiveDirectorySite FindByName(DirectoryContext context, string si { ADSearcher adSearcher = new ADSearcher(de, "(&(objectClass=site)(objectCategory=site)(name=" + Utils.GetEscapedFilterValue(siteName) + "))", - new string[] { "distinguishedName" }, + s_distinguishedName, SearchScope.OneLevel, false, /* don't need paged search */ false /* don't need to cache result */); @@ -709,6 +709,14 @@ private DirectoryEntry NTDSSiteEntry } } + internal static readonly string[] s_distinguishedName = new string[] { "distinguishedName" }; + private static readonly string[] s_propertiesToLoadArray = new string[] { "fromServer", "distinguishedName", "dNSHostName", "objectCategory" }; + private static readonly string[] s_cnLocation = new string[] { "cn", "location" }; + private static readonly string[] s_cnDistinguishedName = new string[] { "cn", "distinguishedName" }; + private static readonly string[] s_dNSHostName = new string[] { "dNSHostName" }; + private static readonly string[] s_fromServerDistinguishedName = new string[] { "fromServer", "distinguishedName" }; + private static readonly string[] s_dNSHostNameDistinguishedName = new string[] { "dNSHostName", "distinguishedName" }; + public void Save() { if (_disposed) @@ -898,7 +906,7 @@ private ReadOnlyDirectoryServerCollection GetBridgeheadServers() // go through connection objects and find out its fromServer property. ADSearcher adSearcher = new ADSearcher(de, "(|(objectCategory=server)(objectCategory=NTDSConnection))", - new string[] { "fromServer", "distinguishedName", "dNSHostName", "objectCategory" }, + s_propertiesToLoadArray, SearchScope.Subtree, true, /* need paged search */ true /* need cached result as we need to go back to the first record */); @@ -989,7 +997,7 @@ private ReadOnlyDirectoryServerCollection GetBridgeheadServers() str.Append(')'); ADSearcher adSearcher = new ADSearcher(serverEntry, "(&(objectClass=nTDSConnection)(objectCategory=NTDSConnection)" + str.ToString() + ")", - new string[] { "fromServer", "distinguishedName" }, + s_fromServerDistinguishedName, SearchScope.Subtree); SearchResultCollection? conResults = null; try @@ -1132,7 +1140,7 @@ private void GetSubnets() ADSearcher adSearcher = new ADSearcher(de, "(&(objectClass=subnet)(objectCategory=subnet)(siteObject=" + Utils.GetEscapedFilterValue((string)PropertyManager.GetPropertyValue(context, cachedEntry, PropertyManager.DistinguishedName)!) + "))", - new string[] { "cn", "location" }, + s_cnLocation, SearchScope.OneLevel ); SearchResultCollection? results = null; @@ -1176,7 +1184,7 @@ private void GetAdjacentSites() de = DirectoryEntryManager.GetDirectoryEntry(context, transportContainer); ADSearcher adSearcher = new ADSearcher(de, "(&(objectClass=siteLink)(objectCategory=SiteLink)(siteList=" + Utils.GetEscapedFilterValue((string)PropertyManager.GetPropertyValue(context, cachedEntry, PropertyManager.DistinguishedName)!) + "))", - new string[] { "cn", "distinguishedName" }, + s_cnDistinguishedName, SearchScope.Subtree); SearchResultCollection? results = null; @@ -1244,7 +1252,7 @@ private void GetLinks() de = DirectoryEntryManager.GetDirectoryEntry(context, transportContainer); ADSearcher adSearcher = new ADSearcher(de, "(&(objectClass=siteLink)(objectCategory=SiteLink)(siteList=" + Utils.GetEscapedFilterValue((string)PropertyManager.GetPropertyValue(context, cachedEntry, PropertyManager.DistinguishedName)!) + "))", - new string[] { "cn", "distinguishedName" }, + s_cnDistinguishedName, SearchScope.Subtree); SearchResultCollection? results = null; @@ -1359,7 +1367,7 @@ private void GetServers() { ADSearcher adSearcher = new ADSearcher(cachedEntry, "(&(objectClass=server)(objectCategory=server))", - new string[] { "dNSHostName" }, + s_dNSHostName, SearchScope.Subtree); SearchResultCollection? results = null; try @@ -1427,7 +1435,7 @@ private void GetPreferredBridgeheadServers(ActiveDirectoryTransportType transpor DirectoryEntry de = DirectoryEntryManager.GetDirectoryEntry(context, serverContainerDN); ADSearcher adSearcher = new ADSearcher(de, "(&(objectClass=server)(objectCategory=Server)(bridgeheadTransportList=" + Utils.GetEscapedFilterValue(transportDN) + "))", - new string[] { "dNSHostName", "distinguishedName" }, + s_dNSHostNameDistinguishedName, SearchScope.OneLevel); SearchResultCollection? results = null; diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLink.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLink.cs index 388484f8ba0933..0f35f731789691 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLink.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLink.cs @@ -149,7 +149,7 @@ public static ActiveDirectorySiteLink FindByName(DirectoryContext context, strin { ADSearcher adSearcher = new ADSearcher(de, "(&(objectClass=siteLink)(objectCategory=SiteLink)(name=" + Utils.GetEscapedFilterValue(siteLinkName) + "))", - new string[] { "distinguishedName" }, + ActiveDirectorySite.s_distinguishedName, SearchScope.OneLevel, false, /* don't need paged search */ false /* don't need to cache result */ diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLinkBridge.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLinkBridge.cs index 3e936f14be4053..0eee1608c44ad3 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLinkBridge.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySiteLinkBridge.cs @@ -136,7 +136,7 @@ public static ActiveDirectorySiteLinkBridge FindByName(DirectoryContext context, { ADSearcher adSearcher = new ADSearcher(de, "(&(objectClass=siteLinkBridge)(objectCategory=SiteLinkBridge)(name=" + Utils.GetEscapedFilterValue(bridgeName) + "))", - new string[] { "distinguishedName" }, + ActiveDirectorySite.s_distinguishedName, SearchScope.OneLevel, false, /* don't need paged search */ false /* don't need to cache result */); diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySubnet.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySubnet.cs index 95d61b0d76d81a..781fc5d723579e 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySubnet.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ActiveDirectorySubnet.cs @@ -47,7 +47,7 @@ public static ActiveDirectorySubnet FindByName(DirectoryContext context, string { ADSearcher adSearcher = new ADSearcher(de, "(&(objectClass=subnet)(objectCategory=subnet)(name=" + Utils.GetEscapedFilterValue(subnetName) + "))", - new string[] { "distinguishedName" }, + ActiveDirectorySite.s_distinguishedName, SearchScope.OneLevel, false, /* don't need paged search */ false /* don't need to cache result */); diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryServer.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryServer.cs index 4b17c346d0beb6..4e6f43ddbd037e 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryServer.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/DirectoryServer.cs @@ -279,6 +279,10 @@ internal void CheckIfDisposed() internal DirectoryContext Context => context; + private static readonly string[] s_name = new string[] { "name" }; + private static readonly string[] s_cn = new string[] { "cn" }; + private static readonly string[] s_objectClassCn = new string[] { "objectClass", "cn" }; + internal unsafe void CheckConsistencyHelper(IntPtr dsHandle, SafeLibraryHandle libHandle) { // call DsReplicaConsistencyCheck @@ -356,7 +360,7 @@ internal unsafe IntPtr GetReplicationInfoHelper(IntPtr dsHandle, int type, int s DirectoryEntry verifyEntry = DirectoryEntryManager.GetDirectoryEntry(this.context, partition); try { - verifyEntry.RefreshCache(new string[] { "name" }); + verifyEntry.RefreshCache(s_name); } catch (COMException e) { @@ -769,7 +773,7 @@ internal ReplicationConnectionCollection GetInboundConnectionsHelper() ADSearcher adSearcher = new ADSearcher(de, "(&(objectClass=nTDSConnection)(objectCategory=nTDSConnection))", - new string[] { "cn" }, + s_cn, SearchScope.OneLevel); SearchResultCollection? srchResults = null; @@ -808,7 +812,7 @@ internal ReplicationConnectionCollection GetOutboundConnectionsHelper() string serverName = (this is DomainController) ? ((DomainController)this).ServerObjectName : ((AdamInstance)this).ServerObjectName; ADSearcher adSearcher = new ADSearcher(de, "(&(objectClass=nTDSConnection)(objectCategory=nTDSConnection)(fromServer=CN=NTDS Settings," + serverName + "))", - new string[] { "objectClass", "cn" }, + s_objectClassCn, SearchScope.Subtree); SearchResultCollection? results = null; diff --git a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationConnection.cs b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationConnection.cs index 34f3a9e2ab3565..f646278e0f2e57 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationConnection.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/ReplicationConnection.cs @@ -53,7 +53,7 @@ public static ReplicationConnection FindByName(DirectoryContext context, string // doing the search to find the connection object based on its name ADSearcher adSearcher = new ADSearcher(de, "(&(objectClass=nTDSConnection)(objectCategory=NTDSConnection)(name=" + Utils.GetEscapedFilterValue(name) + "))", - new string[] { "distinguishedName" }, + ActiveDirectorySite.s_distinguishedName, SearchScope.OneLevel, false, /* no paged search */ false /* don't cache results */); 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 74e21e9a5d49b5..b8fdc052dc00af 100644 --- a/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Utils.cs +++ b/src/libraries/System.DirectoryServices/src/System/DirectoryServices/ActiveDirectory/Utils.cs @@ -896,7 +896,7 @@ internal static string GetDNFromTransportType(ActiveDirectoryTransportType trans ADSearcher adSearcher = new ADSearcher(de, "(&(objectClass=nTDSDSA)(invocationID=" + stringGuid + "))", - new string[] { "distinguishedName" }, + ActiveDirectorySite.s_distinguishedName, SearchScope.Subtree, false, /* don't need paged search */ false /* don't need to cache result */); 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 170081a2f3874d..bec9d28b7b426e 100644 --- a/src/libraries/System.Formats.Asn1/ref/System.Formats.Asn1.cs +++ b/src/libraries/System.Formats.Asn1/ref/System.Formats.Asn1.cs @@ -100,6 +100,7 @@ public partial class AsnReader public AsnReader(System.ReadOnlyMemory data, System.Formats.Asn1.AsnEncodingRules ruleSet, System.Formats.Asn1.AsnReaderOptions options = default(System.Formats.Asn1.AsnReaderOptions)) { } public bool HasData { get { throw null; } } public System.Formats.Asn1.AsnEncodingRules RuleSet { get { throw null; } } + public System.Formats.Asn1.AsnReader Clone() { throw null; } public System.ReadOnlyMemory PeekContentBytes() { throw null; } public System.ReadOnlyMemory PeekEncodedValue() { throw null; } public System.Formats.Asn1.Asn1Tag PeekTag() { throw 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 aa05e57928c13f..6a0bc94a94786b 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 @@ -807,6 +807,15 @@ public ReadOnlyMemory ReadEncodedValue() return encodedValue; } + /// + /// Clones the current reader. + /// + /// A clone of the current reader. + /// + /// This does not create a clone of the ASN.1 data, only the reader's state is cloned. + /// + public AsnReader Clone() => new AsnReader(_data, RuleSet, _options); + private AsnReader CloneAtSlice(int start, int length) { return new AsnReader(_data.Slice(start, length), RuleSet, _options); diff --git a/src/libraries/System.Formats.Asn1/tests/Reader/ReaderStateTests.cs b/src/libraries/System.Formats.Asn1/tests/Reader/ReaderStateTests.cs index 16f73ab02b8bdd..8da3bd35d77161 100644 --- a/src/libraries/System.Formats.Asn1/tests/Reader/ReaderStateTests.cs +++ b/src/libraries/System.Formats.Asn1/tests/Reader/ReaderStateTests.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 Test.Cryptography; using Xunit; namespace System.Formats.Asn1.Tests.Reader @@ -30,5 +31,71 @@ public static void HasDataAndThrowIfNotEmpty_StartsEmpty() // Assert.NoThrow reader.ThrowIfNotEmpty(); } + + [Fact] + public static void Clone_CopiesCurrentState() + { + // Sequence { + // SetOf { + // UtcTime 500405000012Z + // Null + // } + // } + // Verify the options are preserved in the clone by observing them: + // this is an incorrectly sorted SET OF with a date of 50/04/05 that should be 2050, not 1950. + ReadOnlyMemory asn = "30133111170D3530303430353030303031325A0500".HexToByteArray(); + + AsnReaderOptions options = new AsnReaderOptions + { + UtcTimeTwoDigitYearMax = 2050, + SkipSetSortOrderVerification = true, + }; + + AsnReader sequence = new AsnReader(asn, AsnEncodingRules.DER, options); + AsnReader reader = sequence.ReadSequence(); + sequence.ThrowIfNotEmpty(); + + AsnReader clone = reader.Clone(); + Assert.Equal(reader.RuleSet, clone.RuleSet); + + AssertReader(reader); + Assert.False(reader.HasData, "reader.HasData"); + Assert.True(clone.HasData, "clone.HasData"); + + AssertReader(clone); + Assert.False(clone.HasData, "clone.HasData"); + + static void AssertReader(AsnReader reader) + { + AsnReader setOf = reader.ReadSetOf(); + reader.ThrowIfNotEmpty(); + + DateTimeOffset dateTime = setOf.ReadUtcTime(); + Assert.Equal(2050, dateTime.Year); + setOf.ReadNull(); + setOf.ThrowIfNotEmpty(); + } + } + + [Fact] + public static void Clone_Empty() + { + AsnReader reader = new AsnReader(ReadOnlyMemory.Empty, AsnEncodingRules.DER); + AsnReader clone = reader.Clone(); + Assert.False(reader.HasData, "reader.HasData"); + Assert.False(clone.HasData, "clone.HasData"); + } + + [Fact] + public static void Clone_SameUnderlyingData() + { + ReadOnlyMemory data = "04050102030405".HexToByteArray(); + AsnReader reader = new AsnReader(data, AsnEncodingRules.DER); + AsnReader clone = reader.Clone(); + + Assert.True(reader.TryReadPrimitiveOctetString(out ReadOnlyMemory readerData)); + Assert.True(clone.TryReadPrimitiveOctetString(out ReadOnlyMemory cloneData)); + Assert.True(readerData.Span == cloneData.Span, "readerData == cloneData"); + } } } diff --git a/src/libraries/System.Formats.Tar/src/Resources/Strings.resx b/src/libraries/System.Formats.Tar/src/Resources/Strings.resx index 0ece0c6c561528..1c5a56c4da1496 100644 --- a/src/libraries/System.Formats.Tar/src/Resources/Strings.resx +++ b/src/libraries/System.Formats.Tar/src/Resources/Strings.resx @@ -1,64 +1,5 @@  - @@ -270,4 +211,7 @@ The value of the extended attribute key '{0}' contains a disallowed '{1}' character. - \ No newline at end of file + + Cannot write the unseekable data stream of entry '{0}' into an unseekable archive stream. + + diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/FieldLocations.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/FieldLocations.cs index 90856330aa2ef8..adc9819b2cab0f 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/FieldLocations.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/FieldLocations.cs @@ -49,5 +49,9 @@ internal static class FieldLocations internal const ushort V7Padding = LinkName + FieldLengths.LinkName; internal const ushort PosixPadding = Prefix + FieldLengths.Prefix; internal const ushort GnuPadding = RealSize + FieldLengths.RealSize; + + internal const ushort V7Data = V7Padding + FieldLengths.V7Padding; + internal const ushort PosixData = PosixPadding + FieldLengths.PosixPadding; + internal const ushort GnuData = GnuPadding + FieldLengths.GnuPadding; } } diff --git a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs index 41be887ed38912..5d9d3a54431906 100644 --- a/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs +++ b/src/libraries/System.Formats.Tar/src/System/Formats/Tar/TarHeader.Write.cs @@ -25,83 +25,163 @@ internal sealed partial class TarHeader private const string GnuLongMetadataName = "././@LongLink"; private const string ArgNameEntry = "entry"; - // Writes the current header as a V7 entry into the archive stream. - internal void WriteAsV7(Stream archiveStream, Span buffer) + internal void WriteAs(TarEntryFormat format, Stream archiveStream, Span buffer) { - WriteV7FieldsToBuffer(buffer); + Debug.Assert(format > TarEntryFormat.Unknown && format <= TarEntryFormat.Gnu); + Debug.Assert(archiveStream.CanSeek || _dataStream == null || _dataStream.CanSeek); - archiveStream.Write(buffer); - - if (_dataStream != null) + if (archiveStream.CanSeek && _dataStream is { CanSeek: false }) + { + WriteWithUnseekableDataStreamAs(format, archiveStream, buffer); + } + else // Seek status of archive does not matter { - WriteData(archiveStream, _dataStream, _size); + long bytesToWrite = GetTotalDataBytesToWrite(); + WriteFieldsToBuffer(format, bytesToWrite, buffer); + archiveStream.Write(buffer); + + if (_dataStream != null) + { + WriteData(archiveStream, _dataStream, _size); + } } } - // Asynchronously writes the current header as a V7 entry into the archive stream and returns the value of the final checksum. - internal async Task WriteAsV7Async(Stream archiveStream, Memory buffer, CancellationToken cancellationToken) + internal async Task WriteAsAsync(TarEntryFormat format, Stream archiveStream, Memory buffer, CancellationToken cancellationToken) { - cancellationToken.ThrowIfCancellationRequested(); + Debug.Assert(format > TarEntryFormat.Unknown && format <= TarEntryFormat.Gnu); + Debug.Assert(archiveStream.CanSeek || _dataStream == null || _dataStream.CanSeek); - WriteV7FieldsToBuffer(buffer.Span); - - await archiveStream.WriteAsync(buffer, cancellationToken).ConfigureAwait(false); - - if (_dataStream != null) + if (archiveStream.CanSeek && _dataStream is { CanSeek: false }) { - await WriteDataAsync(archiveStream, _dataStream, _size, cancellationToken).ConfigureAwait(false); + await WriteWithUnseekableDataStreamAsAsync(format, archiveStream, buffer, cancellationToken).ConfigureAwait(false); + } + else // seek status of archive does not matter + { + long bytesToWrite = GetTotalDataBytesToWrite(); + WriteFieldsToBuffer(format, bytesToWrite, buffer.Span); + await archiveStream.WriteAsync(buffer, cancellationToken).ConfigureAwait(false); + + if (_dataStream != null) + { + await WriteDataAsync(archiveStream, _dataStream, _size, cancellationToken).ConfigureAwait(false); + } } } - // Writes the V7 header fields to the specified buffer, calculates and writes the checksum, then returns the final data length. - private void WriteV7FieldsToBuffer(Span buffer) + private void WriteWithUnseekableDataStreamAs(TarEntryFormat format, Stream archiveStream, Span buffer) { - _size = GetTotalDataBytesToWrite(); - TarEntryType actualEntryType = TarHelpers.GetCorrectTypeFlagForFormat(TarEntryFormat.V7, _typeFlag); + // When the data stream is unseekable, the order in which we write the entry data changes + Debug.Assert(archiveStream.CanSeek); + Debug.Assert(_dataStream != null); + Debug.Assert(!_dataStream.CanSeek); - int tmpChecksum = WriteName(buffer); - tmpChecksum += WriteCommonFields(buffer, actualEntryType); - _checksum = WriteChecksum(tmpChecksum, buffer); - } + // Store the start of the current entry's header, it'll be used later + long headerStartPosition = archiveStream.Position; - // Writes the current header as a Ustar entry into the archive stream. - internal void WriteAsUstar(Stream archiveStream, Span buffer) - { - WriteUstarFieldsToBuffer(buffer); + ushort dataLocation = format switch + { + TarEntryFormat.V7 => FieldLocations.V7Data, + TarEntryFormat.Ustar or TarEntryFormat.Pax => FieldLocations.PosixData, + TarEntryFormat.Gnu => FieldLocations.GnuData, + _ => throw new ArgumentOutOfRangeException(nameof(format)) + }; + + // We know the exact location where the data starts depending on the format + long dataStartPosition = headerStartPosition + dataLocation; + + // Move to the data start location and write the data + archiveStream.Seek(dataLocation, SeekOrigin.Current); + _dataStream.CopyTo(archiveStream); // The data gets copied from the current position + + // Get the new archive stream position, and the difference is the size of the data stream + long dataEndPosition = archiveStream.Position; + long actualLength = dataEndPosition - dataStartPosition; + + // Write the padding now so that we can go back to writing the entry's header metadata + WriteEmptyPadding(archiveStream, actualLength); + + // Store the end of the current header, we will write the next one after this position + long endOfHeaderPosition = archiveStream.Position; + // Go back to the start of the entry header to write the rest of the fields + archiveStream.Position = headerStartPosition; + + WriteFieldsToBuffer(format, actualLength, buffer); archiveStream.Write(buffer); - if (_dataStream != null) - { - WriteData(archiveStream, _dataStream, _size); - } + // Finally, move to the end of the header to continue with the next entry + archiveStream.Position = endOfHeaderPosition; } - // Asynchronously rites the current header as a Ustar entry into the archive stream and returns the value of the final checksum. - internal async Task WriteAsUstarAsync(Stream archiveStream, Memory buffer, CancellationToken cancellationToken) + // Asynchronously writes the entry in the order required to be able to obtain the unseekable data stream size. + private async Task WriteWithUnseekableDataStreamAsAsync(TarEntryFormat format, Stream archiveStream, Memory buffer, CancellationToken cancellationToken) { - cancellationToken.ThrowIfCancellationRequested(); + // When the data stream is unseekable, the order in which we write the entry data changes + Debug.Assert(archiveStream.CanSeek); + Debug.Assert(_dataStream != null); + Debug.Assert(!_dataStream.CanSeek); + + // Store the start of the current entry's header, it'll be used later + long headerStartPosition = archiveStream.Position; + + ushort dataLocation = format switch + { + TarEntryFormat.V7 => FieldLocations.V7Data, + TarEntryFormat.Ustar or TarEntryFormat.Pax => FieldLocations.PosixData, + TarEntryFormat.Gnu => FieldLocations.GnuData, + _ => throw new ArgumentOutOfRangeException(nameof(format)) + }; - WriteUstarFieldsToBuffer(buffer.Span); + // We know the exact location where the data starts depending on the format + long dataStartPosition = headerStartPosition + dataLocation; + // Move to the data start location and write the data + archiveStream.Seek(dataLocation, SeekOrigin.Current); + await _dataStream.CopyToAsync(archiveStream, cancellationToken).ConfigureAwait(false); // The data gets copied from the current position + + // Get the new archive stream position, and the difference is the size of the data stream + long dataEndPosition = archiveStream.Position; + long actualLength = dataEndPosition - dataStartPosition; + + // Write the padding now so that we can go back to writing the entry's header metadata + await WriteEmptyPaddingAsync(archiveStream, actualLength, cancellationToken).ConfigureAwait(false); + + // Store the end of the current header, we will write the next one after this position + long endOfHeaderPosition = archiveStream.Position; + + // Go back to the start of the entry header to write the rest of the fields + archiveStream.Position = headerStartPosition; + + WriteFieldsToBuffer(format, actualLength, buffer.Span); await archiveStream.WriteAsync(buffer, cancellationToken).ConfigureAwait(false); - if (_dataStream != null) - { - await WriteDataAsync(archiveStream, _dataStream, _size, cancellationToken).ConfigureAwait(false); - } + // Finally, move to the end of the header to continue with the next entry + archiveStream.Position = endOfHeaderPosition; + } + + // Writes the V7 header fields to the specified buffer, calculates and writes the checksum, then returns the final data length. + private void WriteV7FieldsToBuffer(long size, Span buffer) + { + _size = size; + TarEntryType actualEntryType = TarHelpers.GetCorrectTypeFlagForFormat(TarEntryFormat.V7, _typeFlag); + + int tmpChecksum = WriteName(buffer); + tmpChecksum += WriteCommonFields(buffer, actualEntryType); + _checksum = WriteChecksum(tmpChecksum, buffer); } // Writes the Ustar header fields to the specified buffer, calculates and writes the checksum, then returns the final data length. - private void WriteUstarFieldsToBuffer(Span buffer) + private void WriteUstarFieldsToBuffer(long size, Span buffer) { - _size = GetTotalDataBytesToWrite(); + _size = size; TarEntryType actualEntryType = TarHelpers.GetCorrectTypeFlagForFormat(TarEntryFormat.Ustar, _typeFlag); int tmpChecksum = WriteUstarName(buffer); tmpChecksum += WriteCommonFields(buffer, actualEntryType); tmpChecksum += WritePosixMagicAndVersion(buffer); tmpChecksum += WritePosixAndGnuSharedFields(buffer); + _checksum = WriteChecksum(tmpChecksum, buffer); } @@ -140,13 +220,12 @@ internal void WriteAsPax(Stream archiveStream, Span buffer) // First, we write the preceding extended attributes header TarHeader extendedAttributesHeader = new(TarEntryFormat.Pax); // Fill the current header's dict - _size = GetTotalDataBytesToWrite(); CollectExtendedAttributesFromStandardFieldsIfNeeded(); // And pass the attributes to the preceding extended attributes header for writing extendedAttributesHeader.WriteAsPaxExtendedAttributes(archiveStream, buffer, ExtendedAttributes, isGea: false, globalExtendedAttributesEntryNumber: -1); buffer.Clear(); // Reset it to reuse it // Second, we write this header as a normal one - WriteAsPaxInternal(archiveStream, buffer); + WriteAs(TarEntryFormat.Pax, archiveStream, buffer); } // Asynchronously writes the current header as a PAX entry into the archive stream. @@ -159,14 +238,13 @@ internal async Task WriteAsPaxAsync(Stream archiveStream, Memory buffer, C // First, we write the preceding extended attributes header TarHeader extendedAttributesHeader = new(TarEntryFormat.Pax); // Fill the current header's dict - _size = GetTotalDataBytesToWrite(); CollectExtendedAttributesFromStandardFieldsIfNeeded(); // And pass the attributes to the preceding extended attributes header for writing await extendedAttributesHeader.WriteAsPaxExtendedAttributesAsync(archiveStream, buffer, ExtendedAttributes, isGea: false, globalExtendedAttributesEntryNumber: -1, cancellationToken).ConfigureAwait(false); buffer.Span.Clear(); // Reset it to reuse it // Second, we write this header as a normal one - await WriteAsPaxInternalAsync(archiveStream, buffer, cancellationToken).ConfigureAwait(false); + await WriteAsAsync(TarEntryFormat.Pax, archiveStream, buffer, cancellationToken).ConfigureAwait(false); } // Writes the current header as a Gnu entry into the archive stream. @@ -177,7 +255,7 @@ internal void WriteAsGnu(Stream archiveStream, Span buffer) if (_linkName != null && Encoding.UTF8.GetByteCount(_linkName) > FieldLengths.LinkName) { TarHeader longLinkHeader = GetGnuLongMetadataHeader(TarEntryType.LongLink, _linkName); - longLinkHeader.WriteAsGnuInternal(archiveStream, buffer); + longLinkHeader.WriteAs(TarEntryFormat.Gnu, archiveStream, buffer); buffer.Clear(); // Reset it to reuse it } @@ -185,12 +263,12 @@ internal void WriteAsGnu(Stream archiveStream, Span buffer) if (Encoding.UTF8.GetByteCount(_name) > FieldLengths.Name) { TarHeader longPathHeader = GetGnuLongMetadataHeader(TarEntryType.LongPath, _name); - longPathHeader.WriteAsGnuInternal(archiveStream, buffer); + longPathHeader.WriteAs(TarEntryFormat.Gnu, archiveStream, buffer); buffer.Clear(); // Reset it to reuse it } // Third, we write this header as a normal one - WriteAsGnuInternal(archiveStream, buffer); + WriteAs(TarEntryFormat.Gnu, archiveStream, buffer); } // Writes the current header as a Gnu entry into the archive stream. @@ -203,7 +281,7 @@ internal async Task WriteAsGnuAsync(Stream archiveStream, Memory buffer, C if (_linkName != null && Encoding.UTF8.GetByteCount(_linkName) > FieldLengths.LinkName) { TarHeader longLinkHeader = GetGnuLongMetadataHeader(TarEntryType.LongLink, _linkName); - await longLinkHeader.WriteAsGnuInternalAsync(archiveStream, buffer, cancellationToken).ConfigureAwait(false); + await longLinkHeader.WriteAsAsync(TarEntryFormat.Gnu, archiveStream, buffer, cancellationToken).ConfigureAwait(false); buffer.Span.Clear(); // Reset it to reuse it } @@ -211,12 +289,12 @@ internal async Task WriteAsGnuAsync(Stream archiveStream, Memory buffer, C if (Encoding.UTF8.GetByteCount(_name) > FieldLengths.Name) { TarHeader longPathHeader = GetGnuLongMetadataHeader(TarEntryType.LongPath, _name); - await longPathHeader.WriteAsGnuInternalAsync(archiveStream, buffer, cancellationToken).ConfigureAwait(false); + await longPathHeader.WriteAsAsync(TarEntryFormat.Gnu, archiveStream, buffer, cancellationToken).ConfigureAwait(false); buffer.Span.Clear(); // Reset it to reuse it } // Third, we write this header as a normal one - await WriteAsGnuInternalAsync(archiveStream, buffer, cancellationToken).ConfigureAwait(false); + await WriteAsAsync(TarEntryFormat.Gnu, archiveStream, buffer, cancellationToken).ConfigureAwait(false); } // Creates and returns a GNU long metadata header, with the specified long text written into its data stream. @@ -237,38 +315,10 @@ private static TarHeader GetGnuLongMetadataHeader(TarEntryType entryType, string return longMetadataHeader; } - // Writes the current header as a GNU entry into the archive stream. - internal void WriteAsGnuInternal(Stream archiveStream, Span buffer) - { - WriteAsGnuSharedInternal(buffer); - - archiveStream.Write(buffer); - - if (_dataStream != null) - { - WriteData(archiveStream, _dataStream, _size); - } - } - - // Asynchronously writes the current header as a GNU entry into the archive stream. - internal async Task WriteAsGnuInternalAsync(Stream archiveStream, Memory buffer, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - WriteAsGnuSharedInternal(buffer.Span); - - await archiveStream.WriteAsync(buffer, cancellationToken).ConfigureAwait(false); - - if (_dataStream != null) - { - await WriteDataAsync(archiveStream, _dataStream, _size, cancellationToken).ConfigureAwait(false); - } - } - // Shared checksum and data length calculations for GNU entry writing. - private void WriteAsGnuSharedInternal(Span buffer) + private void WriteGnuFieldsToBuffer(long size, Span buffer) { - _size = GetTotalDataBytesToWrite(); + _size = size; int tmpChecksum = WriteName(buffer); tmpChecksum += WriteCommonFields(buffer, TarHelpers.GetCorrectTypeFlagForFormat(TarEntryFormat.Gnu, _typeFlag)); @@ -283,7 +333,7 @@ private void WriteAsGnuSharedInternal(Span buffer) private void WriteAsPaxExtendedAttributes(Stream archiveStream, Span buffer, Dictionary extendedAttributes, bool isGea, int globalExtendedAttributesEntryNumber) { WriteAsPaxExtendedAttributesShared(isGea, globalExtendedAttributesEntryNumber, extendedAttributes); - WriteAsPaxInternal(archiveStream, buffer); + WriteAs(TarEntryFormat.Pax, archiveStream, buffer); } // Asynchronously writes the current header as a PAX Extended Attributes entry into the archive stream and returns the value of the final checksum. @@ -291,7 +341,7 @@ private Task WriteAsPaxExtendedAttributesAsync(Stream archiveStream, Memory buffer) - { - WriteAsPaxSharedInternal(buffer); - - archiveStream.Write(buffer); - - if (_dataStream != null) - { - WriteData(archiveStream, _dataStream, _size); - } - } - - // Both the Extended Attributes and Global Extended Attributes entry headers are written in a similar way, just the data changes - // This method asynchronously writes an entry as both entries require, using the data from the current header instance. - private async Task WriteAsPaxInternalAsync(Stream archiveStream, Memory buffer, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - WriteAsPaxSharedInternal(buffer.Span); - - await archiveStream.WriteAsync(buffer, cancellationToken).ConfigureAwait(false); - - if (_dataStream != null) - { - await WriteDataAsync(archiveStream, _dataStream, _size, cancellationToken).ConfigureAwait(false); - } - } - // Shared checksum and data length calculations for PAX entry writing. - private void WriteAsPaxSharedInternal(Span buffer) + private void WritePaxFieldsToBuffer(long size, Span buffer) { + _size = size; int tmpChecksum = WriteName(buffer); tmpChecksum += WriteCommonFields(buffer, TarHelpers.GetCorrectTypeFlagForFormat(TarEntryFormat.Pax, _typeFlag)); tmpChecksum += WritePosixMagicAndVersion(buffer); @@ -350,6 +370,26 @@ private void WriteAsPaxSharedInternal(Span buffer) _checksum = WriteChecksum(tmpChecksum, buffer); } + // Writes the format-specific fields of the current entry, as well as the entry data length, into the specified buffer. + private void WriteFieldsToBuffer(TarEntryFormat format, long bytesToWrite, Span buffer) + { + switch (format) + { + case TarEntryFormat.V7: + WriteV7FieldsToBuffer(bytesToWrite, buffer); + break; + case TarEntryFormat.Ustar: + WriteUstarFieldsToBuffer(bytesToWrite, buffer); + break; + case TarEntryFormat.Pax: + WritePaxFieldsToBuffer(bytesToWrite, buffer); + break; + case TarEntryFormat.Gnu: + WriteGnuFieldsToBuffer(bytesToWrite, buffer); + break; + } + } + // Gnu and pax save in the name byte array only the UTF8 bytes that fit. // V7 does not support more than 100 bytes so it throws. private int WriteName(Span buffer) @@ -507,18 +547,18 @@ private int WriteCommonFields(Span buffer, TarEntryType actualEntryType) } // Calculates how many data bytes should be written, depending on the position pointer of the stream. + // Only works if the stream is seekable. private long GetTotalDataBytesToWrite() { - if (_dataStream != null) + if (_dataStream == null) { - long length = _dataStream.Length; - long position = _dataStream.Position; - if (position < length) - { - return length - position; - } + return 0; } - return 0; + + long length = _dataStream.Length; + long position = _dataStream.Position; + + return position < length ? length - position : 0; } // Writes the magic and version fields of a ustar or pax entry into the specified spans. @@ -609,18 +649,38 @@ private int WriteGnuFields(Span buffer) private static void WriteData(Stream archiveStream, Stream dataStream, long actualLength) { dataStream.CopyTo(archiveStream); // The data gets copied from the current position + WriteEmptyPadding(archiveStream, actualLength); + } + // Calculates the padding for the current entry and writes it after the data. + private static void WriteEmptyPadding(Stream archiveStream, long actualLength) + { int paddingAfterData = TarHelpers.CalculatePadding(actualLength); if (paddingAfterData != 0) { Debug.Assert(paddingAfterData <= TarHelpers.RecordSize); - Span padding = stackalloc byte[TarHelpers.RecordSize]; - padding = padding.Slice(0, paddingAfterData); - padding.Clear(); + Span zeros = stackalloc byte[TarHelpers.RecordSize]; + zeros = zeros.Slice(0, paddingAfterData); + zeros.Clear(); + + archiveStream.Write(zeros); + } + } + + // Calculates the padding for the current entry and asynchronously writes it after the data. + private static ValueTask WriteEmptyPaddingAsync(Stream archiveStream, long actualLength, CancellationToken cancellationToken) + { + int paddingAfterData = TarHelpers.CalculatePadding(actualLength); + if (paddingAfterData != 0) + { + Debug.Assert(paddingAfterData <= TarHelpers.RecordSize); - archiveStream.Write(padding); + byte[] zeros = new byte[paddingAfterData]; + return archiveStream.WriteAsync(zeros, cancellationToken); } + + return ValueTask.CompletedTask; } // Asynchronously writes the current header's data stream into the archive stream. 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 c4ec17272a8b85..13654eaa7279e6 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 @@ -222,6 +222,7 @@ public void WriteEntry(TarEntry entry) ObjectDisposedException.ThrowIf(_isDisposed, this); ArgumentNullException.ThrowIfNull(entry); ValidateEntryLinkName(entry._header._typeFlag, entry._header._linkName); + ValidateStreamsSeekability(entry); WriteEntryInternal(entry); } @@ -270,6 +271,7 @@ public Task WriteEntryAsync(TarEntry entry, CancellationToken cancellationToken ObjectDisposedException.ThrowIf(_isDisposed, this); ArgumentNullException.ThrowIfNull(entry); ValidateEntryLinkName(entry._header._typeFlag, entry._header._linkName); + ValidateStreamsSeekability(entry); return WriteEntryAsyncInternal(entry, cancellationToken); } @@ -281,12 +283,8 @@ private void WriteEntryInternal(TarEntry entry) switch (entry.Format) { - case TarEntryFormat.V7: - entry._header.WriteAsV7(_archiveStream, buffer); - break; - - case TarEntryFormat.Ustar: - entry._header.WriteAsUstar(_archiveStream, buffer); + case TarEntryFormat.V7 or TarEntryFormat.Ustar: + entry._header.WriteAs(entry.Format, _archiveStream, buffer); break; case TarEntryFormat.Pax: @@ -323,8 +321,7 @@ private async Task WriteEntryAsyncInternal(TarEntry entry, CancellationToken can Task task = entry.Format switch { - TarEntryFormat.V7 => entry._header.WriteAsV7Async(_archiveStream, buffer, cancellationToken), - TarEntryFormat.Ustar => entry._header.WriteAsUstarAsync(_archiveStream, buffer, cancellationToken), + TarEntryFormat.V7 or TarEntryFormat.Ustar => entry._header.WriteAsAsync(entry.Format, _archiveStream, buffer, cancellationToken), TarEntryFormat.Pax when entry._header._typeFlag is TarEntryType.GlobalExtendedAttributes => entry._header.WriteAsPaxGlobalExtendedAttributesAsync(_archiveStream, buffer, _nextGlobalExtendedAttributesEntryNumber++, cancellationToken), TarEntryFormat.Pax => entry._header.WriteAsPaxAsync(_archiveStream, buffer, cancellationToken), TarEntryFormat.Gnu => entry._header.WriteAsGnuAsync(_archiveStream, buffer, cancellationToken), @@ -374,6 +371,14 @@ private async ValueTask WriteFinalRecordsAsync() return (fullPath, actualEntryName); } + private void ValidateStreamsSeekability(TarEntry entry) + { + if (!_archiveStream.CanSeek && entry._header._dataStream != null && !entry._header._dataStream.CanSeek) + { + throw new IOException(SR.Format(SR.TarStreamSeekabilityUnsupportedCombination, entry.Name)); + } + } + private static void ValidateEntryLinkName(TarEntryType entryType, string? linkName) { if (entryType is TarEntryType.HardLink or TarEntryType.SymbolicLink) diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs index ab90f0043bc7d9..bf3cec4fcb0832 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectory.Stream.Tests.cs @@ -1,9 +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.Collections.Generic; using System.IO; using System.IO.Compression; +using System.IO.Enumeration; using System.Linq; using Xunit; @@ -204,5 +204,65 @@ public void PaxNameCollision_DedupInExtendedAttributes() Assert.True(File.Exists(path1)); Assert.True(Path.Exists(path2)); } + + [Theory] + [MemberData(nameof(GetTestTarFormats))] + public void UnseekableStreams_RoundTrip(TestTarFormat testFormat) + { + using TempDirectory root = new(); + + using MemoryStream sourceStream = GetTarMemoryStream(CompressionMethod.Uncompressed, testFormat, "many_small_files"); + using WrappedStream sourceUnseekableArchiveStream = new(sourceStream, canRead: true, canWrite: false, canSeek: false); + + TarFile.ExtractToDirectory(sourceUnseekableArchiveStream, root.Path, overwriteFiles: false); + + using MemoryStream destinationStream = new(); + using WrappedStream destinationUnseekableArchiveStream = new(destinationStream, canRead: true, canWrite: true, canSeek: false); + TarFile.CreateFromDirectory(root.Path, destinationUnseekableArchiveStream, includeBaseDirectory: false); + + FileSystemEnumerable fileSystemEntries = new FileSystemEnumerable( + directory: root.Path, + transform: (ref FileSystemEntry entry) => entry.ToFileSystemInfo(), + options: new EnumerationOptions() { RecurseSubdirectories = true }); + + destinationStream.Position = 0; + using TarReader reader = new TarReader(destinationStream, leaveOpen: false); + + // Size of files in many_small_files.tar are expected to be tiny and all equal + int bufferLength = 1024; + byte[] fileContent = new byte[bufferLength]; + byte[] dataStreamContent = new byte[bufferLength]; + TarEntry entry = reader.GetNextEntry(); + do + { + Assert.NotNull(entry); + string entryPath = Path.TrimEndingDirectorySeparator(Path.GetFullPath(Path.Join(root.Path, entry.Name))); + FileSystemInfo fsi = fileSystemEntries.SingleOrDefault(file => + file.FullName == entryPath); + Assert.NotNull(fsi); + if (entry.EntryType is TarEntryType.RegularFile or TarEntryType.V7RegularFile) + { + Assert.NotNull(entry.DataStream); + + using Stream fileData = File.OpenRead(fsi.FullName); + + // If the size of the files in manu_small_files.tar ever gets larger than bufferLength, + // these asserts should fail and the test will need to be updated + AssertExtensions.LessThanOrEqualTo(entry.Length, bufferLength); + AssertExtensions.LessThanOrEqualTo(fileData.Length, bufferLength); + + Assert.Equal(fileData.Length, entry.Length); + + Array.Clear(fileContent); + Array.Clear(dataStreamContent); + + fileData.ReadExactly(fileContent, 0, (int)entry.Length); + entry.DataStream.ReadExactly(dataStreamContent, 0, (int)entry.Length); + + AssertExtensions.SequenceEqual(fileContent, dataStreamContent); + } + } + while ((entry = reader.GetNextEntry()) != null); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.Stream.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.Stream.Tests.cs index d7502d940e94e6..307a165099f4fe 100644 --- a/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.Stream.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarFile/TarFile.ExtractToDirectoryAsync.Stream.Tests.cs @@ -1,9 +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.Collections.Generic; using System.IO; using System.IO.Compression; +using System.IO.Enumeration; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -269,5 +269,65 @@ public async Task PaxNameCollision_DedupInExtendedAttributesAsync() Assert.True(File.Exists(path1)); Assert.True(Path.Exists(path2)); } + + [Theory] + [MemberData(nameof(GetTestTarFormats))] + public async Task UnseekableStreams_RoundTrip_Async(TestTarFormat testFormat) + { + using TempDirectory root = new(); + + await using MemoryStream sourceStream = GetTarMemoryStream(CompressionMethod.Uncompressed, testFormat, "many_small_files"); + await using WrappedStream sourceUnseekableArchiveStream = new(sourceStream, canRead: true, canWrite: false, canSeek: false); + + await TarFile.ExtractToDirectoryAsync(sourceUnseekableArchiveStream, root.Path, overwriteFiles: false); + + await using MemoryStream destinationStream = new(); + await using WrappedStream destinationUnseekableArchiveStream = new(destinationStream, canRead: true, canWrite: true, canSeek: false); + await TarFile.CreateFromDirectoryAsync(root.Path, destinationUnseekableArchiveStream, includeBaseDirectory: false); + + FileSystemEnumerable fileSystemEntries = new FileSystemEnumerable( + directory: root.Path, + transform: (ref FileSystemEntry entry) => entry.ToFileSystemInfo(), + options: new EnumerationOptions() { RecurseSubdirectories = true }); + + destinationStream.Position = 0; + await using TarReader reader = new TarReader(destinationStream, leaveOpen: false); + + // Size of files in many_small_files.tar are expected to be tiny and all equal + int bufferLength = 1024; + byte[] fileContent = new byte[bufferLength]; + byte[] dataStreamContent = new byte[bufferLength]; + TarEntry entry = await reader.GetNextEntryAsync(); + do + { + Assert.NotNull(entry); + string entryPath = Path.TrimEndingDirectorySeparator(Path.GetFullPath(Path.Join(root.Path, entry.Name))); + FileSystemInfo fsi = fileSystemEntries.SingleOrDefault(file => + file.FullName == entryPath); + Assert.NotNull(fsi); + if (entry.EntryType is TarEntryType.RegularFile or TarEntryType.V7RegularFile) + { + Assert.NotNull(entry.DataStream); + + await using Stream fileData = File.OpenRead(fsi.FullName); + + // If the size of the files in manu_small_files.tar ever gets larger than bufferLength, + // these asserts should fail and the test will need to be updated + AssertExtensions.LessThanOrEqualTo(entry.Length, bufferLength); + AssertExtensions.LessThanOrEqualTo(fileData.Length, bufferLength); + + Assert.Equal(fileData.Length, entry.Length); + + Array.Clear(fileContent); + Array.Clear(dataStreamContent); + + await fileData.ReadExactlyAsync(fileContent, 0, (int)entry.Length); + await entry.DataStream.ReadExactlyAsync(dataStreamContent, 0, (int)entry.Length); + + AssertExtensions.SequenceEqual(fileContent, dataStreamContent); + } + } + while ((entry = await reader.GetNextEntryAsync()) != null); + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntry.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntry.Tests.cs index 2cede3a350c825..ad87b69e08cef2 100644 --- a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntry.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntry.Tests.cs @@ -161,13 +161,18 @@ public void GetNextEntry_CopyDataTrue_UnseekableArchive() Assert.Throws(() => entry.DataStream.Read(new byte[1])); } - [Fact] - public void GetNextEntry_CopyDataFalse_UnseekableArchive_Exceptions() + [Theory] + [InlineData(TarEntryFormat.V7)] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public void GetNextEntry_CopyDataFalse_UnseekableArchive_Exceptions(TarEntryFormat format) { - MemoryStream archive = new MemoryStream(); - using (TarWriter writer = new TarWriter(archive, TarEntryFormat.Ustar, leaveOpen: true)) + TarEntryType fileEntryType = GetTarEntryTypeForTarEntryFormat(TarEntryType.RegularFile, format); + using MemoryStream archive = new MemoryStream(); + using (TarWriter writer = new TarWriter(archive, format, leaveOpen: true)) { - UstarTarEntry entry1 = new UstarTarEntry(TarEntryType.RegularFile, "file.txt"); + TarEntry entry1 = InvokeTarEntryCreationConstructor(format, fileEntryType, "file.txt"); entry1.DataStream = new MemoryStream(); using (StreamWriter streamWriter = new StreamWriter(entry1.DataStream, leaveOpen: true)) { @@ -176,30 +181,34 @@ public void GetNextEntry_CopyDataFalse_UnseekableArchive_Exceptions() entry1.DataStream.Seek(0, SeekOrigin.Begin); // Rewind to ensure it gets written from the beginning writer.WriteEntry(entry1); - UstarTarEntry entry2 = new UstarTarEntry(TarEntryType.Directory, "dir"); + TarEntry entry2 = InvokeTarEntryCreationConstructor(format, TarEntryType.Directory, "dir"); writer.WriteEntry(entry2); } archive.Seek(0, SeekOrigin.Begin); using WrappedStream wrapped = new WrappedStream(archive, canRead: true, canWrite: false, canSeek: false); - UstarTarEntry entry; + TarEntry entry; + byte[] b = new byte[1]; using (TarReader reader = new TarReader(wrapped)) // Unseekable { - entry = reader.GetNextEntry(copyData: false) as UstarTarEntry; + entry = reader.GetNextEntry(copyData: false); Assert.NotNull(entry); - Assert.Equal(TarEntryType.RegularFile, entry.EntryType); + Assert.Equal(fileEntryType, entry.EntryType); entry.DataStream.ReadByte(); // Reading is possible as long as we don't move to the next entry // Attempting to read the next entry should automatically move the position pointer to the beginning of the next header - Assert.NotNull(reader.GetNextEntry()); + TarEntry entry2 = reader.GetNextEntry(); + Assert.NotNull(entry2); + Assert.Equal(format, entry2.Format); + Assert.Equal(TarEntryType.Directory, entry2.EntryType); Assert.Null(reader.GetNextEntry()); // This is not possible because the position of the main stream is already past the data - Assert.Throws(() => entry.DataStream.Read(new byte[1])); + Assert.Throws(() => entry.DataStream.Read(b)); } // The reader must stay alive because it's in charge of disposing all the entries it collected - Assert.Throws(() => entry.DataStream.Read(new byte[1])); + Assert.Throws(() => entry.DataStream.Read(b)); } [Theory] diff --git a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntryAsync.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntryAsync.Tests.cs index f99e5853ebeaad..1c266ae6334345 100644 --- a/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntryAsync.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarReader/TarReader.GetNextEntryAsync.Tests.cs @@ -191,49 +191,56 @@ public async Task GetNextEntry_CopyDataTrue_UnseekableArchive_Async() } } - [Fact] - public async Task GetNextEntry_CopyDataFalse_UnseekableArchive_Exceptions_Async() + [Theory] + [InlineData(TarEntryFormat.V7)] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public async Task GetNextEntry_CopyDataFalse_UnseekableArchive_Exceptions_Async(TarEntryFormat format) { - await using (MemoryStream archive = new MemoryStream()) + TarEntryType fileEntryType = GetTarEntryTypeForTarEntryFormat(TarEntryType.RegularFile, format); + await using MemoryStream archive = new MemoryStream(); + await using (TarWriter writer = new TarWriter(archive, format, leaveOpen: true)) { - await using (TarWriter writer = new TarWriter(archive, TarEntryFormat.Ustar, leaveOpen: true)) + TarEntry entry1 = InvokeTarEntryCreationConstructor(format, fileEntryType, "file.txt"); + entry1.DataStream = new MemoryStream(); + using (StreamWriter streamWriter = new StreamWriter(entry1.DataStream, leaveOpen: true)) { - UstarTarEntry entry1 = new UstarTarEntry(TarEntryType.RegularFile, "file.txt"); - entry1.DataStream = new MemoryStream(); - using (StreamWriter streamWriter = new StreamWriter(entry1.DataStream, leaveOpen: true)) - { - streamWriter.WriteLine("Hello world!"); - } - entry1.DataStream.Seek(0, SeekOrigin.Begin); // Rewind to ensure it gets written from the beginning - await writer.WriteEntryAsync(entry1); - - UstarTarEntry entry2 = new UstarTarEntry(TarEntryType.Directory, "dir"); - await writer.WriteEntryAsync(entry2); + streamWriter.WriteLine("Hello world!"); } + entry1.DataStream.Seek(0, SeekOrigin.Begin); // Rewind to ensure it gets written from the beginning + await writer.WriteEntryAsync(entry1); - archive.Seek(0, SeekOrigin.Begin); - await using (WrappedStream wrapped = new WrappedStream(archive, canRead: true, canWrite: false, canSeek: false)) - { - UstarTarEntry entry; - await using (TarReader reader = new TarReader(wrapped)) // Unseekable - { - entry = await reader.GetNextEntryAsync(copyData: false) as UstarTarEntry; - Assert.NotNull(entry); - Assert.Equal(TarEntryType.RegularFile, entry.EntryType); - entry.DataStream.ReadByte(); // Reading is possible as long as we don't move to the next entry - - // Attempting to read the next entry should automatically move the position pointer to the beginning of the next header - Assert.NotNull(await reader.GetNextEntryAsync()); - Assert.Null(await reader.GetNextEntryAsync()); + TarEntry entry2 = InvokeTarEntryCreationConstructor(format, TarEntryType.Directory, "dir"); + await writer.WriteEntryAsync(entry2); + } - // This is not possible because the position of the main stream is already past the data - Assert.Throws(() => entry.DataStream.Read(new byte[1])); - } + archive.Seek(0, SeekOrigin.Begin); + await using WrappedStream wrapped = new WrappedStream(archive, canRead: true, canWrite: false, canSeek: false); + TarEntry entry; + byte[] b = new byte[1]; + await using (TarReader reader = new TarReader(wrapped)) // Unseekable + { + entry = await reader.GetNextEntryAsync(copyData: false); + Assert.NotNull(entry); + Assert.Equal(format, entry.Format); + Assert.Equal(fileEntryType, entry.EntryType); + entry.DataStream.ReadByte(); // Reading is possible as long as we don't move to the next entry + + // Attempting to read the next entries should automatically move the position pointer to the beginning of the next header + TarEntry entry2 = await reader.GetNextEntryAsync(); + Assert.NotNull(entry2); + Assert.Equal(format, entry2.Format); + Assert.Equal(TarEntryType.Directory, entry2.EntryType); + Assert.Null(await reader.GetNextEntryAsync()); - // The reader must stay alive because it's in charge of disposing all the entries it collected - Assert.Throws(() => entry.DataStream.Read(new byte[1])); - } + // This is not possible because the position of the main stream is already past the data + await Assert.ThrowsAsync(async () => await entry.DataStream.ReadAsync(b)); } + + // The reader must stay alive because it's in charge of disposing all the entries it collected + await Assert.ThrowsAsync(async () => await entry.DataStream.ReadAsync(b)); + } [Theory] diff --git a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs index 3363d279463958..e62b5d045d5521 100644 --- a/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs +++ b/src/libraries/System.Formats.Tar/tests/TarTestsBase.cs @@ -489,6 +489,14 @@ protected static TarEntry InvokeTarEntryCreationConstructor(TarEntryFormat targe _ => throw new InvalidDataException($"Unexpected format: {targetFormat}") }; + public static IEnumerable GetTestTarFormats() + { + foreach (TestTarFormat testFormat in Enum.GetValues()) + { + yield return new object[] { testFormat }; + } + } + public static IEnumerable GetFormatsAndLinks() { foreach (TarEntryFormat format in new[] { TarEntryFormat.V7, TarEntryFormat.Ustar, TarEntryFormat.Pax, TarEntryFormat.Gnu }) diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Base.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Base.cs index efe7c68ced6bb9..334a27e51fa92b 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Base.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Base.cs @@ -1,11 +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; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; using System.Threading.Tasks; using Xunit; diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs index 94522d54a61734..487c6ab04dbcd5 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntry.Tests.cs @@ -21,14 +21,18 @@ public void WriteEntry_AfterDispose_Throws() Assert.Throws(() => writer.WriteEntry(entry)); } - [Fact] - public void WriteEntry_FromUnseekableStream_AdvanceDataStream_WriteFromThatPosition() + + [Theory] + [InlineData(TarEntryFormat.V7)] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public void WriteEntry_FromUnseekableStream_AdvanceDataStream_WriteFromThatPosition(TarEntryFormat format) { using MemoryStream source = GetTarMemoryStream(CompressionMethod.Uncompressed, TestTarFormat.ustar, "file"); using WrappedStream unseekable = new WrappedStream(source, canRead: true, canWrite: true, canSeek: false); using MemoryStream destination = new MemoryStream(); - using (TarReader reader1 = new TarReader(unseekable)) { TarEntry entry = reader1.GetNextEntry(); @@ -39,6 +43,8 @@ public void WriteEntry_FromUnseekableStream_AdvanceDataStream_WriteFromThatPosit using (TarWriter writer = new TarWriter(destination, TarEntryFormat.Ustar, leaveOpen: true)) { writer.WriteEntry(entry); + TarEntry dirEntry = InvokeTarEntryCreationConstructor(format, TarEntryType.Directory, "dir"); + writer.WriteEntry(dirEntry); // To validate that next entry is not affected } } @@ -54,6 +60,14 @@ public void WriteEntry_FromUnseekableStream_AdvanceDataStream_WriteFromThatPosit string contents = streamReader.ReadLine(); Assert.Equal("ello file", contents); } + + TarEntry dirEntry = reader2.GetNextEntry(); + Assert.NotNull(dirEntry); + Assert.Equal(format, dirEntry.Format); + Assert.Equal(TarEntryType.Directory, dirEntry.EntryType); + Assert.Equal("dir", dirEntry.Name); + + Assert.Null(reader2.GetNextEntry()); } } @@ -502,8 +516,8 @@ public void WriteEntry_FileSizeOverLegacyLimit_Throws(TarEntryFormat entryFormat { const long FileSizeOverLimit = LegacyMaxFileSize + 1; - MemoryStream ms = new(); - Stream s = unseekableStream ? new WrappedStream(ms, ms.CanRead, ms.CanWrite, canSeek: false) : ms; + using MemoryStream ms = new(); + using Stream s = unseekableStream ? new WrappedStream(ms, ms.CanRead, ms.CanWrite, canSeek: false) : ms; using TarWriter writer = new(s); TarEntry writeEntry = InvokeTarEntryCreationConstructor(entryFormat, entryFormat is TarEntryFormat.V7 ? TarEntryType.V7RegularFile : TarEntryType.RegularFile, "foo"); @@ -513,5 +527,77 @@ public void WriteEntry_FileSizeOverLegacyLimit_Throws(TarEntryFormat entryFormat Assert.Throws(() => writer.WriteEntry(writeEntry)); } + + [Theory] + [InlineData(TarEntryFormat.V7)] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public void WritingUnseekableDataStream_To_UnseekableArchiveStream_Throws(TarEntryFormat entryFormat) + { + using MemoryStream internalDataStream = new(); + using WrappedStream unseekableDataStream = new(internalDataStream, canRead: true, canWrite: false, canSeek: false); + + using MemoryStream internalArchiveStream = new(); + using WrappedStream unseekableArchiveStream = new(internalArchiveStream, canRead: true, canWrite: true, canSeek: false); + + using TarWriter writer = new(unseekableArchiveStream); + TarEntry entry = InvokeTarEntryCreationConstructor(entryFormat, GetTarEntryTypeForTarEntryFormat(TarEntryType.RegularFile, entryFormat), "file.txt"); + entry.DataStream = unseekableDataStream; + Assert.Throws(() => writer.WriteEntry(entry)); + } + + [Theory] + [InlineData(TarEntryFormat.V7)] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public void Write_TwoEntries_With_UnseekableDataStreams(TarEntryFormat entryFormat) + { + byte[] expectedBytes = new byte[] { 0x1, 0x2, 0x3, 0x4, 0x5 }; + + using MemoryStream internalDataStream1 = new(); + internalDataStream1.Write(expectedBytes.AsSpan()); + internalDataStream1.Position = 0; + + TarEntryType fileEntryType = GetTarEntryTypeForTarEntryFormat(TarEntryType.RegularFile, entryFormat); + + using WrappedStream unseekableDataStream1 = new(internalDataStream1, canRead: true, canWrite: false, canSeek: false); + TarEntry entry1 = InvokeTarEntryCreationConstructor(entryFormat, fileEntryType, "file1.txt"); + entry1.DataStream = unseekableDataStream1; + + using MemoryStream internalDataStream2 = new(); + internalDataStream2.Write(expectedBytes.AsSpan()); + internalDataStream2.Position = 0; + + using WrappedStream unseekableDataStream2 = new(internalDataStream2, canRead: true, canWrite: false, canSeek: false); + TarEntry entry2 = InvokeTarEntryCreationConstructor(entryFormat, fileEntryType, "file2.txt"); + entry2.DataStream = unseekableDataStream2; + + using MemoryStream archiveStream = new(); + using (TarWriter writer = new(archiveStream, leaveOpen: true)) + { + writer.WriteEntry(entry1); // Should not throw + writer.WriteEntry(entry2); // To verify that second entry is written in correct place + } + + // Verify + archiveStream.Position = 0; + byte[] actualBytes = new byte[] { 0, 0, 0, 0, 0 }; + using (TarReader reader = new(archiveStream)) + { + TarEntry readEntry = reader.GetNextEntry(); + Assert.NotNull(readEntry); + readEntry.DataStream.ReadExactly(actualBytes); + Assert.Equal(expectedBytes, actualBytes); + + readEntry = reader.GetNextEntry(); + Assert.NotNull(readEntry); + readEntry.DataStream.ReadExactly(actualBytes); + Assert.Equal(expectedBytes, actualBytes); + + Assert.Null(reader.GetNextEntry()); + } + } } } diff --git a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Tests.cs b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Tests.cs index f0d4d238b2f8e8..45b26ad66e6005 100644 --- a/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Tests.cs +++ b/src/libraries/System.Formats.Tar/tests/TarWriter/TarWriter.WriteEntryAsync.Tests.cs @@ -43,8 +43,12 @@ public async Task WriteEntry_AfterDispose_Throws_Async() await Assert.ThrowsAsync(() => writer.WriteEntryAsync(entry)); } - [Fact] - public async Task WriteEntry_FromUnseekableStream_AdvanceDataStream_WriteFromThatPosition_Async() + [Theory] + [InlineData(TarEntryFormat.V7)] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public async Task WriteEntry_FromUnseekableStream_AdvanceDataStream_WriteFromThatPosition_Async(TarEntryFormat format) { using MemoryStream source = GetTarMemoryStream(CompressionMethod.Uncompressed, TestTarFormat.ustar, "file"); using WrappedStream unseekable = new WrappedStream(source, canRead: true, canWrite: true, canSeek: false); @@ -57,9 +61,11 @@ public async Task WriteEntry_FromUnseekableStream_AdvanceDataStream_WriteFromTha Assert.NotNull(entry.DataStream); entry.DataStream.ReadByte(); // Advance one byte, now the expected string would be "ello file" - await using (TarWriter writer = new TarWriter(destination, TarEntryFormat.Ustar, leaveOpen: true)) + await using (TarWriter writer = new TarWriter(destination, format, leaveOpen: true)) { await writer.WriteEntryAsync(entry); + TarEntry dirEntry = InvokeTarEntryCreationConstructor(format, TarEntryType.Directory, "dir"); + await writer.WriteEntryAsync(dirEntry); // To validate that next entry is not affected } } @@ -75,6 +81,14 @@ public async Task WriteEntry_FromUnseekableStream_AdvanceDataStream_WriteFromTha string contents = streamReader.ReadLine(); Assert.Equal("ello file", contents); } + + TarEntry dirEntry = await reader2.GetNextEntryAsync(); + Assert.NotNull(dirEntry); + Assert.Equal(format, dirEntry.Format); + Assert.Equal(TarEntryType.Directory, dirEntry.EntryType); + Assert.Equal("dir", dirEntry.Name); + + Assert.Null(await reader2.GetNextEntryAsync()); } } @@ -420,8 +434,8 @@ public async Task WriteEntry_FileSizeOverLegacyLimit_Throws_Async(TarEntryFormat { const long FileSizeOverLimit = LegacyMaxFileSize + 1; - MemoryStream ms = new(); - Stream s = unseekableStream ? new WrappedStream(ms, ms.CanRead, ms.CanWrite, canSeek: false) : ms; + await using MemoryStream ms = new(); + await using Stream s = unseekableStream ? new WrappedStream(ms, ms.CanRead, ms.CanWrite, canSeek: false) : ms; string tarFilePath = GetTestFilePath(); await using TarWriter writer = new(File.Create(tarFilePath)); @@ -432,5 +446,77 @@ public async Task WriteEntry_FileSizeOverLegacyLimit_Throws_Async(TarEntryFormat await Assert.ThrowsAsync(() => writer.WriteEntryAsync(writeEntry)); } + + [Theory] + [InlineData(TarEntryFormat.V7)] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public async Task WritingUnseekableDataStream_To_UnseekableArchiveStream_Throws_Async(TarEntryFormat entryFormat) + { + await using MemoryStream internalDataStream = new(); + await using WrappedStream unseekableDataStream = new(internalDataStream, canRead: true, canWrite: false, canSeek: false); + + await using MemoryStream internalArchiveStream = new(); + await using WrappedStream unseekableArchiveStream = new(internalArchiveStream, canRead: true, canWrite: true, canSeek: false); + + await using TarWriter writer = new(unseekableArchiveStream); + TarEntry entry = InvokeTarEntryCreationConstructor(entryFormat, GetTarEntryTypeForTarEntryFormat(TarEntryType.RegularFile, entryFormat), "file.txt"); + entry.DataStream = unseekableDataStream; + await Assert.ThrowsAsync(() => writer.WriteEntryAsync(entry)); + } + + [Theory] + [InlineData(TarEntryFormat.V7)] + [InlineData(TarEntryFormat.Ustar)] + [InlineData(TarEntryFormat.Pax)] + [InlineData(TarEntryFormat.Gnu)] + public async Task Write_TwoEntries_With_UnseekableDataStreams_Async(TarEntryFormat entryFormat) + { + byte[] expectedBytes = new byte[] { 0x1, 0x2, 0x3, 0x4, 0x5 }; + + await using MemoryStream internalDataStream1 = new(); + await internalDataStream1.WriteAsync(expectedBytes.AsMemory()); + internalDataStream1.Position = 0; + + TarEntryType fileEntryType = GetTarEntryTypeForTarEntryFormat(TarEntryType.RegularFile, entryFormat); + + await using WrappedStream unseekableDataStream1 = new(internalDataStream1, canRead: true, canWrite: false, canSeek: false); + TarEntry entry1 = InvokeTarEntryCreationConstructor(entryFormat, fileEntryType, "file1.txt"); + entry1.DataStream = unseekableDataStream1; + + await using MemoryStream internalDataStream2 = new(); + await internalDataStream2.WriteAsync(expectedBytes.AsMemory()); + internalDataStream2.Position = 0; + + await using WrappedStream unseekableDataStream2 = new(internalDataStream2, canRead: true, canWrite: false, canSeek: false); + TarEntry entry2 = InvokeTarEntryCreationConstructor(entryFormat, fileEntryType, "file2.txt"); + entry2.DataStream = unseekableDataStream2; + + await using MemoryStream archiveStream = new(); + await using (TarWriter writer = new(archiveStream, leaveOpen: true)) + { + await writer.WriteEntryAsync(entry1); // Should not throw + await writer.WriteEntryAsync(entry2); // To verify that second entry is written in correct place + } + + // Verify + archiveStream.Position = 0; + byte[] actualBytes = new byte[] { 0, 0, 0, 0, 0 }; + await using (TarReader reader = new(archiveStream)) + { + TarEntry readEntry = await reader.GetNextEntryAsync(); + Assert.NotNull(readEntry); + await readEntry.DataStream.ReadExactlyAsync(actualBytes); + Assert.Equal(expectedBytes, actualBytes); + + readEntry = await reader.GetNextEntryAsync(); + Assert.NotNull(readEntry); + await readEntry.DataStream.ReadExactlyAsync(actualBytes); + Assert.Equal(expectedBytes, actualBytes); + + Assert.Null(await reader.GetNextEntryAsync()); + } + } } } diff --git a/src/libraries/System.Globalization.Extensions/tests/Hybrid/System.Globalization.Extensions.Hybrid.WASM.Tests.csproj b/src/libraries/System.Globalization.Extensions/tests/Hybrid/System.Globalization.Extensions.Hybrid.WASM.Tests.csproj deleted file mode 100644 index 0e7c98c19436f5..00000000000000 --- a/src/libraries/System.Globalization.Extensions/tests/Hybrid/System.Globalization.Extensions.Hybrid.WASM.Tests.csproj +++ /dev/null @@ -1,20 +0,0 @@ - - - $(NetCoreAppCurrent)-browser - true - true - - - - - - - - - NormalizationDataWin8 - - - NormalizationDataWin7 - - - diff --git a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs index f53ed73cc7f067..329bf076d500c2 100644 --- a/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.cs +++ b/src/libraries/System.Globalization/tests/CultureInfo/CultureInfoCtor.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 Microsoft.DotNet.RemoteExecutor; using System.Collections.Generic; using Xunit; @@ -434,13 +435,65 @@ public void TestCreationWithTemporaryLCID(int lcid) Assert.NotEqual(lcid, new CultureInfo(lcid).LCID); } - [InlineData("zh-TW-u-co-zhuyin")] - [InlineData("de-DE-u-co-phoneb")] - [InlineData("de-u-co-phonebk")] + [InlineData("zh-TW-u-co-zhuyin", "zh-TW", "zh-TW_zhuyin")] + [InlineData("de-DE-u-co-phonebk", "de-DE", "de-DE_phoneboo")] + [InlineData("de-DE-u-co-phonebk-u-xx", "de-DE-u-xx", "de-DE-u-xx_phoneboo")] + [InlineData("de-DE-u-xx-u-co-phonebk", "de-DE-u-xx-u-co-phonebk", "de-DE-u-xx-u-co-phonebk")] + [InlineData("de-DE-t-xx-u-co-phonebk", "de-DE-t-xx-u-co-phonebk", "de-DE-t-xx-u-co-phonebk_phoneboo")] + [InlineData("de-DE-u-co-phonebk-t-xx", "de-DE-t-xx", "de-DE-t-xx_phoneboo")] + [InlineData("de-DE-u-co-phonebk-t-xx-u-yy", "de-DE-t-xx-u-yy", "de-DE-t-xx-u-yy_phoneboo")] + [InlineData("de-DE", "de-DE", "de-DE")] [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalization))] - public void TestCreationWithMangledSortName(string cultureName) + public void TestCreationWithMangledSortName(string cultureName, string expectedCultureName, string expectedSortName) + { + CultureInfo ci = CultureInfo.GetCultureInfo(cultureName); + + Assert.Equal(expectedCultureName, ci.Name); + Assert.Equal(expectedSortName, ci.CompareInfo.Name); + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalization))] + public void TestNeutralCultureWithCollationName() { - Assert.True(CultureInfo.GetCultureInfo(cultureName).CompareInfo.Name.Equals(cultureName, StringComparison.OrdinalIgnoreCase)); + Assert.Throws(() => CultureInfo.GetCultureInfo("zh-u-co-zhuyin")); + Assert.Throws(() => CultureInfo.GetCultureInfo("de-u-co-phonebk")); + } + + [InlineData("xx-u-XX", "xx-u-xx")] + [InlineData("xx-u-XX-u-yy", "xx-u-xx-u-yy")] + [InlineData("xx-t-ja-JP", "xx-t-ja-jp")] + [InlineData("qps-plocm", "qps-PLOCM")] // ICU normalize this name to "qps--plocm" which we normalize it back to "qps-plocm" + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsIcuGlobalization))] + public void TestCreationWithICUNormalizedNames(string cultureName, string expectedCultureName) + { + CultureInfo ci = CultureInfo.GetCultureInfo(cultureName); + Assert.Equal(expectedCultureName, ci.Name); + } + + private static bool SupportRemoteExecutionWithIcu => RemoteExecutor.IsSupported && PlatformDetection.IsIcuGlobalization; + + [InlineData("xx-u-XX")] + [InlineData("xx-u-XX-u-yy")] + [InlineData("xx-t-ja-JP")] + [InlineData("qps-plocm")] + [InlineData("zh-TW-u-co-zhuyin")] + [InlineData("de-DE-u-co-phonebk")] + [InlineData("de-DE-u-co-phonebk-u-xx")] + [InlineData("de-DE-u-xx-u-co-phonebk")] + [InlineData("de-DE-t-xx-u-co-phonebk")] + [InlineData("de-DE-u-co-phonebk-t-xx")] + [InlineData("de-DE-u-co-phonebk-t-xx-u-yy")] + [InlineData("de-DE")] + [ConditionalTheory(nameof(SupportRemoteExecutionWithIcu))] + public void TestWithResourceLookup(string cultureName) + { + RemoteExecutor.Invoke(name => { + CultureInfo.CurrentUICulture = CultureInfo.GetCultureInfo(name); + int Zero = 0; + + // This should go through the resource manager to get the localized exception message using the current UI culture + Assert.Throws(() => 1 / Zero); + }, cultureName).Dispose(); } } } diff --git a/src/libraries/System.Globalization/tests/Invariant/InvariantMode.cs b/src/libraries/System.Globalization/tests/Invariant/InvariantMode.cs index 361c39ec4272b8..fd2d62a59934b6 100644 --- a/src/libraries/System.Globalization/tests/Invariant/InvariantMode.cs +++ b/src/libraries/System.Globalization/tests/Invariant/InvariantMode.cs @@ -1196,6 +1196,16 @@ public void TestGetCultureInfo_PredefinedOnly_ReturnsSame() Assert.Equal(CultureInfo.GetCultureInfo("en-US"), CultureInfo.GetCultureInfo("en-US", predefinedOnly: true)); } + [ConditionalTheory(nameof(PredefinedCulturesOnlyIsDisabled))] + [InlineData(0x0001)] + [InlineData(0x7c5C)] + [InlineData(0x03_0404)] // with sort id + [InlineData(0x007F)] // LOCALE_INVARIANT + public void TestCultureInfo_Ctor_Int32_ReturnsInvariant(int culture) + { + Assert.Equal(new CultureInfo(culture), CultureInfo.InvariantCulture); + } + private static byte[] GetExpectedInvariantOrdinalSortKey(ReadOnlySpan input) { MemoryStream memoryStream = new MemoryStream(); diff --git a/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFile.Create.cs b/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFile.Create.cs index ba088ab15d024c..5cd64ca6156bd7 100644 --- a/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFile.Create.cs +++ b/src/libraries/System.IO.Compression.ZipFile/src/System/IO/Compression/ZipFile.Create.cs @@ -459,10 +459,7 @@ private static void DoCreateFromDirectory(string sourceDirectoryName, Stream des throw new ArgumentOutOfRangeException(nameof(compressionLevel)); } - // Rely on Path.GetFullPath for validation of sourceDirectoryName and destinationArchive - - // Checking of compressionLevel is passed down to DeflateStream and the IDeflater implementation - // as it is a pluggable component that completely encapsulates the meaning of compressionLevel. + // Rely on Path.GetFullPath for validation of sourceDirectoryName sourceDirectoryName = Path.GetFullPath(sourceDirectoryName); diff --git a/src/libraries/System.IO.Compression/src/Resources/Strings.resx b/src/libraries/System.IO.Compression/src/Resources/Strings.resx index 94fa155281d93a..86e181e97ff13b 100644 --- a/src/libraries/System.IO.Compression/src/Resources/Strings.resx +++ b/src/libraries/System.IO.Compression/src/Resources/Strings.resx @@ -230,9 +230,6 @@ Offset to Zip64 End Of Central Directory record cannot be held in an Int64. - - Start Disk Number cannot be held in an Int64. - Uncompressed Size cannot be held in an Int64. 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 1fd84d715f6d5a..3d415f8e3690f1 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 @@ -18,7 +18,7 @@ public partial class ZipArchiveEntry { private ZipArchive _archive; private readonly bool _originallyInArchive; - private readonly int _diskNumberStart; + private readonly uint _diskNumberStart; private readonly ZipVersionMadeByPlatform _versionMadeByPlatform; private ZipVersionNeededValues _versionMadeBySpecification; internal ZipVersionNeededValues _versionToExtract; diff --git a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs index fb186dfcfc9f37..8bcb5495efe461 100644 --- a/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs +++ b/src/libraries/System.IO.Compression/src/System/IO/Compression/ZipBlocks.cs @@ -96,7 +96,7 @@ internal struct Zip64ExtraField private long? _uncompressedSize; private long? _compressedSize; private long? _localHeaderOffset; - private int? _startDiskNumber; + private uint? _startDiskNumber; public ushort TotalSize => (ushort)(_size + 4); @@ -115,7 +115,7 @@ public long? LocalHeaderOffset get { return _localHeaderOffset; } set { _localHeaderOffset = value; UpdateSize(); } } - public int? StartDiskNumber => _startDiskNumber; + public uint? StartDiskNumber => _startDiskNumber; private void UpdateSize() { @@ -242,7 +242,7 @@ private static bool TryGetZip64BlockFromGenericExtraField(ZipGenericExtraField e if (readStartDiskNumber) { - zip64Block._startDiskNumber = reader.ReadInt32(); + zip64Block._startDiskNumber = reader.ReadUInt32(); } else if (readAllFields) { @@ -253,7 +253,6 @@ private static bool TryGetZip64BlockFromGenericExtraField(ZipGenericExtraField e if (zip64Block._uncompressedSize < 0) throw new InvalidDataException(SR.FieldTooBigUncompressedSize); if (zip64Block._compressedSize < 0) throw new InvalidDataException(SR.FieldTooBigCompressedSize); if (zip64Block._localHeaderOffset < 0) throw new InvalidDataException(SR.FieldTooBigLocalHeaderOffset); - if (zip64Block._startDiskNumber < 0) throw new InvalidDataException(SR.FieldTooBigStartDiskNumber); return true; } @@ -480,7 +479,7 @@ internal struct ZipCentralDirectoryFileHeader public ushort FilenameLength; public ushort ExtraFieldLength; public ushort FileCommentLength; - public int DiskNumberStart; + public uint DiskNumberStart; public ushort InternalFileAttributes; public uint ExternalFileAttributes; public long RelativeOffsetOfLocalHeader; diff --git a/src/libraries/System.IO.Compression/tests/ZipArchive/zip_InvalidParametersAndStrangeFiles.cs b/src/libraries/System.IO.Compression/tests/ZipArchive/zip_InvalidParametersAndStrangeFiles.cs index ec67114972f4d9..f8ab630ba1656e 100644 --- a/src/libraries/System.IO.Compression/tests/ZipArchive/zip_InvalidParametersAndStrangeFiles.cs +++ b/src/libraries/System.IO.Compression/tests/ZipArchive/zip_InvalidParametersAndStrangeFiles.cs @@ -3,6 +3,7 @@ using System.Buffers.Binary; using System.Collections.Generic; +using System.Linq; using System.Text; using System.Threading.Tasks; using Xunit; @@ -860,6 +861,20 @@ public void ReadArchive_WithUnexpectedZip64ExtraFieldSizeUncompressedSizeIn32Bit Assert.Equal(6, entry.CompressedLength); // it should have used 32-bit size } + /// + /// This test checks behavior of ZipArchive when the startDiskNumber in the extraField is greater than IntMax + /// + [Fact] + public void ReadArchive_WithDiskStartNumberGreaterThanIntMax() + { + byte[] input = (byte[])s_zip64WithBigStartDiskNumber.Clone(); + using var archive = new ZipArchive(new MemoryStream(input)); + + var exception = Record.Exception(() => archive.Entries.First()); + + Assert.Null(exception); + } + private static readonly byte[] s_slightlyIncorrectZip64 = { // ===== Local file header signature 0x04034b50 @@ -1000,5 +1015,154 @@ public void ReadArchive_WithUnexpectedZip64ExtraFieldSizeUncompressedSizeIn32Bit // comment length 0x00, 0x00 }; + + private static readonly byte[] s_zip64WithBigStartDiskNumber = + { + // ===== Local file header signature 0x04034b50 + 0x50, 0x4b, 0x03, 0x04, + // version to extract 4.5 + 0x2d, 0x00, + // general purpose flags + 0x00, 0x08, // 0000_1000 'for enhanced deflating' + // Deflate + 0x08, 0x00, + // Last mod file time + 0x17, 0x9b, + // Last mod date + 0x6d, 0x52, + // CRC32 + 0x0c, 0x7e, 0x7f, 0xd8, + // compressed size + 0xff, 0xff, 0xff, 0xff, + // UNcompressed size + 0xff, 0xff, 0xff, 0xff, + // file name length + + 0x08, 0x00, + // extra field length + 0x20, 0x00, + // filename + 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x74, 0x78, 0x74, + // -----Zip64 extra field tag + 0x01, 0x00, + // size of extra field block + 0x20, 0x00, + // 8 byte Zip64 UNcompressed size, index 42 + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // 8 byte Zip64 compressed size, index 50 + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // 8 byte Relative Header Offset + 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Disk Start Number + 0xff, 0xff, 0xff, 0xfe, + // ----- NTFS extra field tag + 0x0a, 0x00, + // size of extra field block + 0x20, 0x00, + // reserved + 0x00, 0x00, 0x00, 0x00, + // tag #1 + 0x01, 0x00, + // size of tag #1 + 0x18, 0x00, + // Mtime, CTime, Atime + 0xa8, 0xb1, 0xf6, 0x61, 0x25, 0x18, 0xd7, 0x01, + 0xa8, 0xb1, 0xf6, 0x61, 0x25, 0x18, 0xd7, 0x01, + 0xa8, 0xb1, 0xf6, 0x61, 0x25, 0x18, 0xd7, 0x01, + // ------------- + // Data! + 0x2b, 0x49, 0x2d, 0x2e, 0x01, 0x00, + // -------- Central directory signature 0x02014b50 + 0x50, 0x4b, 0x01, 0x02, + // version made by 4.5 + 0x2d, 0x00, + // version to extract 4.5 + 0x2d, 0x00, + // general purpose flags + 0x00, 0x08, + // Deflate + 0x08, 0x00, + // Last mod file time + 0x17, 0x9b, + // Last mod date + 0x6d, 0x52, + // CRC32 + 0x0c, 0x7e, 0x7f, 0xd8, + // 4 byte compressed size, index 120 (-1 indicates refer to Zip64 extra field) + 0xff, 0xff, 0xff, 0xff, + // 4 byte UNcompressed size, index 124 (-1 indicates refer to Zip64 extra field) + 0xff, 0xff, 0xff, 0xff, + // file name length + 0x08, 0x00, + // extra field length + 0x44, 0x00, + // file comment length + 0x00, 0x00, + // disk number start (-1 indicates refer to Zip64 extra field) + 0xff, 0xff, + // internal file attributes + 0x00, 0x00, + // external file attributes + 0x00, 0x00, 0x00, 0x00, + // relative offset of local header (-1 indicates refer to Zip64 extra field) + 0x00, 0x00, 0x00, 0x00, + // file name + 0x66, 0x69, 0x6c, 0x65, 0x2e, 0x74, 0x78, 0x74, + // extra field, content similar to before + 0x01, 0x00, + 0x1c, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // Disk start number + 0xff, 0xff, 0xff, 0xfe, + 0x0a, 0x00, + 0x20, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x18, 0x00, + 0xa8, 0xb1, 0xf6, 0x61, 0x25, 0x18, 0xd7, 0x01, + 0xa8, 0xb1, 0xf6, 0x61, 0x25, 0x18, 0xd7, 0x01, + 0xa8, 0xb1, 0xf6, 0x61, 0x25, 0x18, 0xd7, 0x01, + // == 'end of zip64 central directory record' signature 0x06064b50 + 0x50, 0x4b, 0x06, 0x06, + // size + 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // version made by, version needed + 0x2d, 0x00, 0x2d, 0x00, + // disk number, disk number with CD + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // total number of CD records + 0x01, 0x00, 0x00, 0x00, + // size of CD + 0x00, 0x00, 0x00, 0x00, + // offset of start of CD wrt starting disk + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // zip64 extensible data sector + 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // offset of start cd + 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // == 'zip64 end of CD locator' signature 0x07064b50 + 0x50, 0x4b, 0x06, 0x07, + // number of disk with zip64 CD + 0x00, 0x00, 0x00, 0x00, + // relative offset of zip64 ECD + 0xea, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + // total number of disks + 0x01, 0x00, 0x00, 0x00, + // == 'end of CD' signature 0x06054b50 + 0x50, 0x4b, 0x05, 0x06, + // disk number, disk number with CD (-1 indicates refer to Zip64 extra field) + 0x00, 0x00, + 0x00, 0x00, + // total number of entries in CD on this disk, and overall (-1 indicates refer to Zip64 extra fields) + 0xff, 0xff, + 0xff, 0xff, + // size of CD (-1 indicates refer to Zip64 extra field) + 0x7a, 0x00, 0x00, 0x00, + // offset of start of CD wrt start disk (-1 indicates refer to Zip64 extra field) + 0x70, 0x00, 0x00, 0x00, + // comment length + 0x00, 0x00 + }; } } diff --git a/src/libraries/System.Linq.Parallel/tests/ParallelEnumerableTests.cs b/src/libraries/System.Linq.Parallel/tests/ParallelEnumerableTests.cs index a168f8db519705..a45e26bf352a63 100644 --- a/src/libraries/System.Linq.Parallel/tests/ParallelEnumerableTests.cs +++ b/src/libraries/System.Linq.Parallel/tests/ParallelEnumerableTests.cs @@ -181,8 +181,7 @@ public static IEnumerable RepeatData() yield return new object[] { element, count }; yield return new object[] { (long)element, count }; yield return new object[] { (double)element, count }; - // [ActiveIssue("https://github.com/xunit/xunit/issues/1771")] - //yield return new object[] { (decimal)element, count }; + yield return new object[] { (decimal)element, count }; yield return new object[] { "" + element, count }; } yield return new object[] { null, count }; diff --git a/src/libraries/System.Linq.Parallel/tests/QueryOperators/DefaultIfEmptyTests.cs b/src/libraries/System.Linq.Parallel/tests/QueryOperators/DefaultIfEmptyTests.cs index 30358c411633a9..4d628bda77c96a 100644 --- a/src/libraries/System.Linq.Parallel/tests/QueryOperators/DefaultIfEmptyTests.cs +++ b/src/libraries/System.Linq.Parallel/tests/QueryOperators/DefaultIfEmptyTests.cs @@ -109,7 +109,6 @@ public static void DefaultIfEmpty_NotEmpty_NotPipelined_Longrunning(Labeled(Labeled> labeled, T def) { ParallelQuery notEmpty = labeled.Item.DefaultIfEmpty(); @@ -125,7 +124,6 @@ public static void DefaultIfEmpty_Empty(Labeled> labeled, T [Theory] [MemberData(nameof(EmptyData))] - [ActiveIssue("https://github.com/xunit/xunit/issues/1771")] public static void DefaultIfEmpty_Empty_NotPipelined(Labeled> labeled, T def) { IList notEmpty = labeled.Item.DefaultIfEmpty().ToList(); diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs b/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs index 7817707d0bfce5..9dee2cb367fafe 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/BrowserHttpHandler/BrowserHttpHandler.cs @@ -204,16 +204,14 @@ private static async Task CallFetch(HttpRequestMessage reques { if (request.Content is StringContent) { - string body = await request.Content.ReadAsStringAsync(cancellationToken) - .ConfigureAwait(true); + string body = await request.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(true); cancellationToken.ThrowIfCancellationRequested(); promise = BrowserHttpInterop.Fetch(uri, headerNames.ToArray(), headerValues.ToArray(), optionNames, optionValues, abortController, body); } else { - byte[] buffer = await request.Content.ReadAsByteArrayAsync(cancellationToken) - .ConfigureAwait(true); + byte[] buffer = await request.Content.ReadAsByteArrayAsync(cancellationToken).ConfigureAwait(true); cancellationToken.ThrowIfCancellationRequested(); promise = BrowserHttpInterop.Fetch(uri, headerNames.ToArray(), headerValues.ToArray(), optionNames, optionValues, abortController, buffer); @@ -225,8 +223,7 @@ private static async Task CallFetch(HttpRequestMessage reques } cancellationToken.ThrowIfCancellationRequested(); - ValueTask wrappedTask = BrowserHttpInterop.CancelationHelper(promise, cancellationToken, abortController); - JSObject fetchResponse = await wrappedTask.ConfigureAwait(true); + JSObject fetchResponse = await BrowserHttpInterop.CancelationHelper(promise, cancellationToken, abortController).ConfigureAwait(true); return new WasmFetchResponse(fetchResponse, abortRegistration.Value); } catch (Exception) diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs index cfc13bfb9022ac..b2c592a0c63b75 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/Http2Connection.cs @@ -368,7 +368,7 @@ public void ReleaseStream() // Returns true to indicate at least one stream is available // Returns false to indicate that the connection is shutting down and cannot be used anymore - public ValueTask WaitForAvailableStreamsAsync() + public Task WaitForAvailableStreamsAsync() { lock (SyncObject) { @@ -379,17 +379,17 @@ public ValueTask WaitForAvailableStreamsAsync() if (_shutdown) { - return ValueTask.FromResult(false); + return Task.FromResult(false); } if (_streamsInUse < _maxConcurrentStreams) { - return ValueTask.FromResult(true); + return Task.FromResult(true); } // Need to wait for streams to become available. _availableStreamsWaiter = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); - return new ValueTask(_availableStreamsWaiter.Task); + return _availableStreamsWaiter.Task; } } diff --git a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs index 76f904d79b2036..d79d7233f39078 100644 --- a/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs +++ b/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpConnection.cs @@ -390,7 +390,7 @@ void WriteHost(Uri requestUri) _writeBuffer.EnsureAvailableSpace(6); Span buffer = _writeBuffer.AvailableSpan; buffer[0] = (byte)':'; - bool success = Utf8Formatter.TryFormat(requestUri.Port, buffer.Slice(1), out int bytesWritten); + bool success = ((uint)requestUri.Port).TryFormat(buffer.Slice(1), out int bytesWritten); Debug.Assert(success); _writeBuffer.Commit(bytesWritten + 1); } @@ -1493,7 +1493,7 @@ private async ValueTask FlushThenWriteWithoutBufferingAsync(ReadOnlyMemory private ValueTask WriteHexInt32Async(int value, bool async) { // Try to format into our output buffer directly. - if (Utf8Formatter.TryFormat(value, _writeBuffer.AvailableSpan, out int bytesWritten, 'X')) + if (value.TryFormat(_writeBuffer.AvailableSpan, out int bytesWritten, "X")) { _writeBuffer.Commit(bytesWritten); return default; @@ -1502,7 +1502,10 @@ private ValueTask WriteHexInt32Async(int value, bool async) // If we don't have enough room, do it the slow way. if (async) { - return WriteAsync(Encoding.ASCII.GetBytes(value.ToString("X", CultureInfo.InvariantCulture))); + Span temp = stackalloc byte[8]; // max length of Int32 as hex + bool formatted = value.TryFormat(temp, out bytesWritten, "X"); + Debug.Assert(formatted); + return WriteAsync(temp.Slice(0, bytesWritten).ToArray()); } else { 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 index 40f865ea9b8605..c415f5c687d53f 100644 --- 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 @@ -467,6 +467,10 @@ private async Task AddHttp11ConnectionAsync(RequestQueue.QueueIt { 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; @@ -531,12 +535,7 @@ private void CheckForHttp11ConnectionInjection() _pendingHttp11ConnectionCount++; RequestQueue.QueueItem queueItem = _http11RequestQueue.PeekNextRequestForConnectionAttempt(); - - // Queue the creation of the connection to escape the held lock - ThreadPool.QueueUserWorkItem(static state => - { - _ = state.thisRef.AddHttp11ConnectionAsync(state.queueItem); // ignore returned task - }, (thisRef: this, queueItem), preferLocal: true); + _ = AddHttp11ConnectionAsync(queueItem); // ignore returned task } } @@ -667,6 +666,10 @@ private async Task AddHttp2ConnectionAsync(RequestQueue.QueueI { 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; @@ -773,12 +776,7 @@ private void CheckForHttp2ConnectionInjection() _pendingHttp2Connection = true; RequestQueue.QueueItem queueItem = _http2RequestQueue.PeekNextRequestForConnectionAttempt(); - - // Queue the creation of the connection to escape the held lock - ThreadPool.QueueUserWorkItem(static state => - { - _ = state.thisRef.AddHttp2ConnectionAsync(state.queueItem); // ignore returned task - }, (thisRef: this, queueItem), preferLocal: true); + _ = AddHttp2ConnectionAsync(queueItem); // ignore returned task } } @@ -2118,11 +2116,13 @@ private void DisableHttp2Connection(Http2Connection connection) { if (NetEventSource.Log.IsEnabled()) connection.Trace(""); - Task.Run(async () => + _ = DisableHttp2ConnectionAsync(connection); // ignore returned task + + async Task DisableHttp2ConnectionAsync(Http2Connection connection) { - bool usable = await connection.WaitForAvailableStreamsAsync().ConfigureAwait(false); + bool usable = await connection.WaitForAvailableStreamsAsync().ConfigureAwait(ConfigureAwaitOptions.ForceYielding); - if (NetEventSource.Log.IsEnabled()) connection.Trace($"WaitForAvailableStreamsAsync completed, {nameof(usable)}={usable}"); + if (NetEventSource.Log.IsEnabled()) connection.Trace($"{nameof(connection.WaitForAvailableStreamsAsync)} completed, {nameof(usable)}={usable}"); if (usable) { @@ -2144,7 +2144,7 @@ private void DisableHttp2Connection(Http2Connection connection) if (NetEventSource.Log.IsEnabled()) connection.Trace("HTTP2 connection no longer usable"); connection.Dispose(); } - }); + }; } public void InvalidateHttp3Connection(Http3Connection connection) diff --git a/src/libraries/System.Net.HttpListener/src/System/Net/Windows/WebSockets/HttpWebSocket.Windows.cs b/src/libraries/System.Net.HttpListener/src/System/Net/Windows/WebSockets/HttpWebSocket.Windows.cs index 0991741e40093a..e3cf309c3aa3d6 100644 --- a/src/libraries/System.Net.HttpListener/src/System/Net/Windows/WebSockets/HttpWebSocket.Windows.cs +++ b/src/libraries/System.Net.HttpListener/src/System/Net/Windows/WebSockets/HttpWebSocket.Windows.cs @@ -90,7 +90,7 @@ private static async Task AcceptWebSocketAsyncCore NetEventSource.Info(null, $"{HttpKnownHeaderNames.SecWebSocketProtocol} = {outgoingSecWebSocketProtocolString}"); } - await response.OutputStream.FlushAsync().SuppressContextFlow(); + await response.OutputStream.FlushAsync().ConfigureAwait(false); HttpResponseStream responseStream = (response.OutputStream as HttpResponseStream)!; Debug.Assert(responseStream != null, "'responseStream' MUST be castable to System.Net.HttpResponseStream."); @@ -137,22 +137,6 @@ private static async Task AcceptWebSocketAsyncCore return webSocketContext; } - internal static ConfiguredTaskAwaitable SuppressContextFlow(this Task task) - { - // We don't flow the synchronization context within WebSocket.xxxAsync - but the calling application - // can decide whether the completion callback for the task returned from WebSocket.xxxAsync runs - // under the caller's synchronization context. - return task.ConfigureAwait(false); - } - - internal static ConfiguredTaskAwaitable SuppressContextFlow(this Task task) - { - // We don't flow the synchronization context within WebSocket.xxxAsync - but the calling application - // can decide whether the completion callback for the task returned from WebSocket.xxxAsync runs - // under the caller's synchronization context. - return task.ConfigureAwait(false); - } - private static unsafe ulong SendWebSocketHeaders(HttpListenerResponse response) { return response.SendHeaders(null, null, diff --git a/src/libraries/System.Net.HttpListener/src/System/Net/Windows/WebSockets/WebSocketBase.cs b/src/libraries/System.Net.HttpListener/src/System/Net/Windows/WebSockets/WebSocketBase.cs index 555be7683fd919..c1d2e8f81324c5 100644 --- a/src/libraries/System.Net.HttpListener/src/System/Net/Windows/WebSockets/WebSocketBase.cs +++ b/src/libraries/System.Net.HttpListener/src/System/Net/Windows/WebSockets/WebSocketBase.cs @@ -180,7 +180,7 @@ private async Task ReceiveAsyncCore(ArraySegment b } EnsureReceiveOperation(); - receiveResult = (await _receiveOperation!.Process(buffer, linkedCancellationToken).SuppressContextFlow())!; + receiveResult = (await _receiveOperation!.Process(buffer, linkedCancellationToken).ConfigureAwait(false))!; if (NetEventSource.Log.IsEnabled() && receiveResult.Count > 0) { @@ -268,7 +268,7 @@ private async Task SendAsyncCore(ArraySegment buffer, } } - await keepAliveTask.SuppressContextFlow(); + await keepAliveTask.ConfigureAwait(false); ThrowIfPendingException(); _sendOutstandingOperationHelper.CompleteOperation(ownsCancellationTokenSource); @@ -281,7 +281,7 @@ private async Task SendAsyncCore(ArraySegment buffer, EnsureSendOperation(); _sendOperation!.BufferType = GetBufferType(messageType, endOfMessage); - await _sendOperation.Process(buffer, linkedCancellationToken).SuppressContextFlow(); + await _sendOperation.Process(buffer, linkedCancellationToken).ConfigureAwait(false); } catch (Exception exception) { @@ -301,7 +301,7 @@ private async Task SendFrameAsync(IList> sendBuffers, Cancell bool sendFrameLockTaken = false; try { - await _sendFrameThrottle.WaitAsync(cancellationToken).SuppressContextFlow(); + await _sendFrameThrottle.WaitAsync(cancellationToken).ConfigureAwait(false); sendFrameLockTaken = true; if (sendBuffers.Count > 1 && @@ -309,16 +309,14 @@ private async Task SendFrameAsync(IList> sendBuffers, Cancell _innerStreamAsWebSocketStream.SupportsMultipleWrite) { await _innerStreamAsWebSocketStream.MultipleWriteAsync(sendBuffers, - cancellationToken).SuppressContextFlow(); + cancellationToken).ConfigureAwait(false); } else { foreach (ArraySegment buffer in sendBuffers) { - await _innerStream.WriteAsync(buffer.Array!, - buffer.Offset, - buffer.Count, - cancellationToken).SuppressContextFlow(); + await _innerStream.WriteAsync(buffer.Array!.AsMemory(buffer.Offset, buffer.Count), + cancellationToken).ConfigureAwait(false); } } } @@ -425,7 +423,7 @@ private async Task CloseOutputAsyncCore(WebSocketCloseStatus closeStatus, if (closeOutputTask != null) { ReleaseLocks(ref thisLockTaken, ref sessionHandleLockTaken); - await closeOutputTask.SuppressContextFlow(); + await closeOutputTask.ConfigureAwait(false); TakeLocks(ref thisLockTaken, ref sessionHandleLockTaken); } } @@ -441,7 +439,7 @@ private async Task CloseOutputAsyncCore(WebSocketCloseStatus closeStatus, Task keepAliveTask = _keepAliveTask; ReleaseLocks(ref thisLockTaken, ref sessionHandleLockTaken); - await keepAliveTask.SuppressContextFlow(); + await keepAliveTask.ConfigureAwait(false); TakeLocks(ref thisLockTaken, ref sessionHandleLockTaken); ThrowIfPendingException(); @@ -461,7 +459,7 @@ private async Task CloseOutputAsyncCore(WebSocketCloseStatus closeStatus, _closeOutputTask = _closeOutputOperation!.Process(null, linkedCancellationToken); ReleaseLocks(ref thisLockTaken, ref sessionHandleLockTaken); - await _closeOutputTask.SuppressContextFlow(); + await _closeOutputTask.ConfigureAwait(false); TakeLocks(ref thisLockTaken, ref sessionHandleLockTaken); if (OnCloseOutputCompleted()) @@ -471,7 +469,7 @@ private async Task CloseOutputAsyncCore(WebSocketCloseStatus closeStatus, try { callCompleteOnCloseCompleted = await StartOnCloseCompleted( - thisLockTaken, sessionHandleLockTaken, linkedCancellationToken).SuppressContextFlow(); + thisLockTaken, sessionHandleLockTaken, linkedCancellationToken).ConfigureAwait(false); } catch (Exception) { @@ -570,7 +568,7 @@ private async Task StartOnCloseCompleted(bool thisLockTakenSnapshot, ReleaseLock(_thisLock, ref thisLockTaken); } - await _closeNetworkConnectionTask.SuppressContextFlow(); + await _closeNetworkConnectionTask.ConfigureAwait(false); } catch (Exception closeNetworkConnectionTaskException) { @@ -654,7 +652,7 @@ private async Task CloseAsyncCore(WebSocketCloseStatus closeStatus, ReleaseLock(_thisLock, ref lockTaken); try { - await closeOutputTask.SuppressContextFlow(); + await closeOutputTask.ConfigureAwait(false); } catch (Exception closeOutputError) { @@ -687,7 +685,7 @@ private async Task CloseAsyncCore(WebSocketCloseStatus closeStatus, // linkedCancellationToken can be CancellationToken.None if ownsCloseCancellationTokenSource==false // This is still ok because OnCloseOutputCompleted won't start any IO operation in this case callCompleteOnCloseCompleted = await StartOnCloseCompleted( - lockTaken, false, linkedCancellationToken).SuppressContextFlow(); + lockTaken, false, linkedCancellationToken).ConfigureAwait(false); } catch (Exception) { @@ -725,7 +723,7 @@ private async Task CloseAsyncCore(WebSocketCloseStatus closeStatus, WebSocketReceiveResult? receiveResult = null; try { - receiveResult = await receiveAsyncTask.SuppressContextFlow(); + receiveResult = await receiveAsyncTask.ConfigureAwait(false); } catch (Exception receiveException) { @@ -766,7 +764,7 @@ private async Task CloseAsyncCore(WebSocketCloseStatus closeStatus, { _receiveOutstandingOperationHelper.CompleteOperation(ownsReceiveCancellationTokenSource); ReleaseLock(_thisLock, ref lockTaken); - await _closeReceivedTaskCompletionSource!.Task.SuppressContextFlow(); + await _closeReceivedTaskCompletionSource!.Task.ConfigureAwait(false); } // When ownsReceiveCancellationTokenSource is true and an exception is thrown, the lock will be taken. @@ -793,7 +791,7 @@ private async Task CloseAsyncCore(WebSocketCloseStatus closeStatus, // linkedCancellationToken can be CancellationToken.None if ownsCloseCancellationTokenSource==false // This is still ok because OnCloseOutputCompleted won't start any IO operation in this case callCompleteOnCloseCompleted = await StartOnCloseCompleted( - lockTaken, false, linkedCancellationToken).SuppressContextFlow(); + lockTaken, false, linkedCancellationToken).ConfigureAwait(false); } catch (Exception) { @@ -1278,7 +1276,7 @@ private static async void OnKeepAlive(object? sender) thisPtr.EnsureKeepAliveOperation(); thisPtr._keepAliveTask = thisPtr._keepAliveOperation!.Process(null, linkedCancellationToken); ReleaseLock(thisPtr.SessionHandle, ref lockTaken); - await thisPtr._keepAliveTask!.SuppressContextFlow(); + await thisPtr._keepAliveTask!.ConfigureAwait(false); } } finally @@ -1411,7 +1409,7 @@ protected virtual void ProcessAction_IndicateReceiveComplete( try { callCompleteOnCloseCompleted = await _webSocket.StartOnCloseCompleted( - thisLockTaken, sessionHandleLockTaken, cancellationToken).SuppressContextFlow(); + thisLockTaken, sessionHandleLockTaken, cancellationToken).ConfigureAwait(false); } catch (Exception) { @@ -1461,7 +1459,7 @@ protected virtual void ProcessAction_IndicateReceiveComplete( payload.Offset, payload.Count, cancellationToken); - count = await readTask.SuppressContextFlow(); + count = await readTask.ConfigureAwait(false); _webSocket._keepAliveTracker.OnDataReceived(); } catch (ObjectDisposedException objectDisposedException) @@ -1491,7 +1489,7 @@ protected virtual void ProcessAction_IndicateReceiveComplete( WebSocketProtocolComponent.WebSocketCompleteAction(_webSocket, actionContext, 0); AsyncOperationCompleted = true; ReleaseLock(_webSocket.SessionHandle, ref sessionHandleLockTaken); - await _webSocket._innerStream.FlushAsync(cancellationToken).SuppressContextFlow(); + await _webSocket._innerStream.FlushAsync(cancellationToken).ConfigureAwait(false); Monitor.Enter(_webSocket.SessionHandle, ref sessionHandleLockTaken); break; case WebSocketProtocolComponent.Action.SendToNetwork: @@ -1539,7 +1537,7 @@ protected virtual void ProcessAction_IndicateReceiveComplete( ReleaseLock(_webSocket.SessionHandle, ref sessionHandleLockTaken); HttpWebSocket.ThrowIfConnectionAborted(_webSocket._innerStream, false); - await _webSocket.SendFrameAsync(sendBuffers, cancellationToken).SuppressContextFlow(); + await _webSocket.SendFrameAsync(sendBuffers, cancellationToken).ConfigureAwait(false); Monitor.Enter(_webSocket.SessionHandle, ref sessionHandleLockTaken); _webSocket.ThrowIfPendingException(); bytesSent += sendBufferSize; diff --git a/src/libraries/System.Net.HttpListener/src/System/Net/Windows/WebSockets/WebSocketHttpListenerDuplexStream.cs b/src/libraries/System.Net.HttpListener/src/System/Net/Windows/WebSockets/WebSocketHttpListenerDuplexStream.cs index 8cb140eee8403a..e16d8f33bc874f 100644 --- a/src/libraries/System.Net.HttpListener/src/System/Net/Windows/WebSockets/WebSocketHttpListenerDuplexStream.cs +++ b/src/libraries/System.Net.HttpListener/src/System/Net/Windows/WebSockets/WebSocketHttpListenerDuplexStream.cs @@ -141,7 +141,7 @@ private async Task ReadAsyncCore(byte[] buffer, int offset, int count, Canc if (!_inOpaqueMode) { - bytesRead = await _inputStream.ReadAsync(buffer, offset, count, cancellationToken).SuppressContextFlow(); + bytesRead = await _inputStream.ReadAsync(buffer.AsMemory(offset, count), cancellationToken).ConfigureAwait(false); } else { @@ -165,7 +165,7 @@ private async Task ReadAsyncCore(byte[] buffer, int offset, int count, Canc } else { - bytesRead = await _readTaskCompletionSource.Task.SuppressContextFlow(); + bytesRead = await _readTaskCompletionSource.Task.ConfigureAwait(false); } } } @@ -355,7 +355,7 @@ private async Task MultipleWriteAsyncCore(IList> sendBuffers, _writeEventArgs.BufferList = sendBuffers; if (WriteAsyncFast(_writeEventArgs)) { - await _writeTaskCompletionSource.Task.SuppressContextFlow(); + await _writeTaskCompletionSource.Task.ConfigureAwait(false); } } catch (Exception error) @@ -398,7 +398,7 @@ private async Task WriteAsyncCore(byte[] buffer, int offset, int count, Cancella if (!_inOpaqueMode) { - await _outputStream.WriteAsync(buffer, offset, count, cancellationToken).SuppressContextFlow(); + await _outputStream.WriteAsync(buffer.AsMemory(offset, count), cancellationToken).ConfigureAwait(false); } else { @@ -414,7 +414,7 @@ private async Task WriteAsyncCore(byte[] buffer, int offset, int count, Cancella _writeEventArgs.SetBuffer(buffer, offset, count); if (WriteAsyncFast(_writeEventArgs)) { - await _writeTaskCompletionSource.Task.SuppressContextFlow(); + await _writeTaskCompletionSource.Task.ConfigureAwait(false); } } } @@ -573,7 +573,7 @@ public async Task CloseNetworkConnectionAsync(CancellationToken cancellationToke _writeEventArgs!.SetShouldCloseOutput(); if (WriteAsyncFast(_writeEventArgs)) { - await _writeTaskCompletionSource.Task.SuppressContextFlow(); + await _writeTaskCompletionSource.Task.ConfigureAwait(false); } } catch (Exception error) diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Android.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Android.cs index 3bca7060682f66..c9d7f9d67f6096 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Android.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Android.cs @@ -111,7 +111,7 @@ private static void CreateAndStartLoop() Debug.Assert(s_loopTask is null); s_cancellationTokenSource = new CancellationTokenSource(); - s_loopTask = Task.Run(() => PeriodicallyCheckIfNetworkChanged(s_cancellationTokenSource.Token)); + s_loopTask = PeriodicallyCheckIfNetworkChanged(s_cancellationTokenSource.Token); } private static void StopLoop() @@ -128,12 +128,13 @@ private static void StopLoop() private static async Task PeriodicallyCheckIfNetworkChanged(CancellationToken cancellationToken) { - using var timer = new PeriodicTimer(s_timerInterval); + await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); + var timer = new PeriodicTimer(s_timerInterval); try { - while (await timer.WaitForNextTickAsync(cancellationToken).ConfigureAwait(false) - && !cancellationToken.IsCancellationRequested) + while (await timer.WaitForNextTickAsync(cancellationToken).ConfigureAwait(false) && + !cancellationToken.IsCancellationRequested) { CheckIfNetworkChanged(); } @@ -141,6 +142,10 @@ private static async Task PeriodicallyCheckIfNetworkChanged(CancellationToken ca catch (OperationCanceledException) { } + finally + { + timer.Dispose(); + } } private static void CheckIfNetworkChanged() diff --git a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Unix.cs b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Unix.cs index b55a6fe95159e5..38913da8292faa 100644 --- a/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Unix.cs +++ b/src/libraries/System.Net.NetworkInformation/src/System/Net/NetworkInformation/NetworkAddressChange.Unix.cs @@ -166,10 +166,10 @@ private static unsafe void CreateSocket() Marshal.InitHandle(sh, newSocket); Socket = new Socket(sh); - // Don't capture ExecutionContext. - ThreadPool.UnsafeQueueUserWorkItem( - static socket => ReadEventsAsync(socket), - Socket, preferLocal: false); + using (ExecutionContext.SuppressFlow()) + { + _ = ReadEventsAsync(Socket); + } } private static void CloseSocket() @@ -180,8 +180,9 @@ private static void CloseSocket() Socket = null; } - private static async void ReadEventsAsync(Socket socket) + private static async Task ReadEventsAsync(Socket socket) { + await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); try { while (true) @@ -199,9 +200,13 @@ private static async void ReadEventsAsync(Socket socket) } } catch (ObjectDisposedException) - { } // Socket disposed. + { + // Socket disposed. + } catch (SocketException se) when (se.SocketErrorCode == SocketError.OperationAborted) - { } // ReceiveAsync aborted by disposing Socket. + { + // ReceiveAsync aborted by disposing Socket. + } catch (Exception ex) { // Unexpected error. 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 eee513c94073d8..ccb0f93c898622 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 @@ -52,7 +52,7 @@ public sealed partial class QuicConnection : IAsyncDisposable /// Options for the connection. /// A cancellation token that can be used to cancel the asynchronous operation. /// An asynchronous task that completes with the connected connection. - public static async ValueTask ConnectAsync(QuicClientConnectionOptions options, CancellationToken cancellationToken = default) + public static ValueTask ConnectAsync(QuicClientConnectionOptions options, CancellationToken cancellationToken = default) { if (!IsSupported) { @@ -61,18 +61,23 @@ public static async ValueTask ConnectAsync(QuicClientConnectionO // Validate and fill in defaults for the options. options.Validate(nameof(options)); + return StartConnectAsync(options, cancellationToken); - QuicConnection connection = new QuicConnection(); - try - { - await connection.FinishConnectAsync(options, cancellationToken).ConfigureAwait(false); - } - catch + static async ValueTask StartConnectAsync(QuicClientConnectionOptions options, CancellationToken cancellationToken) { - await connection.DisposeAsync().ConfigureAwait(false); - throw; + QuicConnection connection = new QuicConnection(); + try + { + await connection.FinishConnectAsync(options, cancellationToken).ConfigureAwait(false); + } + catch + { + await connection.DisposeAsync().ConfigureAwait(false); + throw; + } + + return connection; } - return connection; } /// @@ -229,8 +234,6 @@ internal unsafe QuicConnection(QUIC_HANDLE* handle, QUIC_NEW_CONNECTION_INFO* in private async ValueTask FinishConnectAsync(QuicClientConnectionOptions options, CancellationToken cancellationToken = default) { - ObjectDisposedException.ThrowIf(_disposed == 1, this); - if (_connectedTcs.TryInitialize(out ValueTask valueTask, this, cancellationToken)) { _canAccept = options.MaxInboundBidirectionalStreams > 0 || options.MaxInboundUnidirectionalStreams > 0; 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 1cf2a5c800cb31..67f4ab96d78884 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 @@ -62,11 +62,11 @@ internal virtual void Validate(string argumentName) { if (MaxInboundBidirectionalStreams < 0 || MaxInboundBidirectionalStreams > ushort.MaxValue) { - throw new ArgumentNullException(SR.Format(SR.net_quic_in_range, nameof(QuicConnectionOptions.MaxInboundBidirectionalStreams), ushort.MaxValue), argumentName); + throw new ArgumentOutOfRangeException(SR.Format(SR.net_quic_in_range, nameof(QuicConnectionOptions.MaxInboundBidirectionalStreams), ushort.MaxValue), argumentName); } if (MaxInboundUnidirectionalStreams < 0 || MaxInboundUnidirectionalStreams > ushort.MaxValue) { - throw new ArgumentNullException(SR.Format(SR.net_quic_in_range, nameof(QuicConnectionOptions.MaxInboundUnidirectionalStreams), ushort.MaxValue), argumentName); + throw new ArgumentOutOfRangeException(SR.Format(SR.net_quic_in_range, nameof(QuicConnectionOptions.MaxInboundUnidirectionalStreams), ushort.MaxValue), argumentName); } if (IdleTimeout < TimeSpan.Zero && IdleTimeout != Timeout.InfiniteTimeSpan) { @@ -74,11 +74,11 @@ internal virtual void Validate(string argumentName) } if (DefaultStreamErrorCode < 0 || DefaultStreamErrorCode > QuicDefaults.MaxErrorCodeValue) { - throw new ArgumentNullException(SR.Format(SR.net_quic_in_range, nameof(QuicConnectionOptions.DefaultStreamErrorCode), QuicDefaults.MaxErrorCodeValue), argumentName); + throw new ArgumentOutOfRangeException(SR.Format(SR.net_quic_in_range, nameof(QuicConnectionOptions.DefaultStreamErrorCode), QuicDefaults.MaxErrorCodeValue), argumentName); } if (DefaultCloseErrorCode < 0 || DefaultCloseErrorCode > QuicDefaults.MaxErrorCodeValue) { - throw new ArgumentNullException(SR.Format(SR.net_quic_in_range, nameof(QuicConnectionOptions.DefaultCloseErrorCode), QuicDefaults.MaxErrorCodeValue), argumentName); + throw new ArgumentOutOfRangeException(SR.Format(SR.net_quic_in_range, nameof(QuicConnectionOptions.DefaultCloseErrorCode), QuicDefaults.MaxErrorCodeValue), argumentName); } } } 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 a8d115e28e0f5f..841ca9b73c913f 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 @@ -212,7 +212,7 @@ private async void StartConnectionHandshake(QuicConnection connection, SslClient CancellationToken cancellationToken = default; try { - CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(_disposeCts.Token); + using CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(_disposeCts.Token); linkedCts.CancelAfter(QuicDefaults.HandshakeTimeout); cancellationToken = linkedCts.Token; QuicServerConnectionOptions options = await _connectionOptionsCallback(connection, clientHello, cancellationToken).ConfigureAwait(false); diff --git a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs index f2c34ebda10b5b..b19ca5650f35a1 100644 --- a/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.cs +++ b/src/libraries/System.Net.Quic/tests/FunctionalTests/QuicConnectionTests.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.Net.Sockets; using System.Security.Cryptography.X509Certificates; using System.Threading; using System.Threading.Tasks; @@ -367,5 +368,46 @@ await Task.WhenAll( await stream.WriteAsync(new byte[1] { data }, completeWrites: true); }).WaitAsync(TimeSpan.FromSeconds(5))); } + + [Fact] + public async Task ConnectAsync_InvalidName_ThrowsSocketException() + { + string name = $"{Guid.NewGuid().ToString("N")}.microsoft.com."; + var options = new QuicClientConnectionOptions() + { + DefaultStreamErrorCode = DefaultStreamErrorCodeClient, + DefaultCloseErrorCode = DefaultCloseErrorCodeClient, + RemoteEndPoint = new DnsEndPoint(name, 10000), + ClientAuthenticationOptions = GetSslClientAuthenticationOptions() + }; + + SocketException ex = await Assert.ThrowsAsync(() => QuicConnection.ConnectAsync(options).AsTask()); + Assert.Equal(SocketError.HostNotFound, ((SocketException)ex).SocketErrorCode ); + } + + [Fact] + public void ConnectAsync_MissingName_ThrowsInvalidArgument() + { + var options = new QuicClientConnectionOptions() + { + DefaultStreamErrorCode = DefaultStreamErrorCodeClient, + DefaultCloseErrorCode = DefaultCloseErrorCodeClient, + ClientAuthenticationOptions = GetSslClientAuthenticationOptions() + }; + + Assert.Throws(() => QuicConnection.ConnectAsync(options)); + } + + [Fact] + public void ConnectAsync_MissingDefaults_ThrowsInvalidArgument() + { + var options = new QuicClientConnectionOptions() + { + RemoteEndPoint = new DnsEndPoint("localhost", 10000), + ClientAuthenticationOptions = GetSslClientAuthenticationOptions() + }; + + Assert.Throws(() => QuicConnection.ConnectAsync(options)); + } } } diff --git a/src/libraries/System.Net.Requests/src/System/Net/FtpControlStream.cs b/src/libraries/System.Net.Requests/src/System/Net/FtpControlStream.cs index 383115cfd94fdc..c97e915d05e911 100644 --- a/src/libraries/System.Net.Requests/src/System/Net/FtpControlStream.cs +++ b/src/libraries/System.Net.Requests/src/System/Net/FtpControlStream.cs @@ -868,6 +868,9 @@ internal string? ExitMessage } } + private static readonly char[] s_whitespaceDot = new char[] { ' ', '.', '\r', '\n' }; + private static readonly char[] s_spaceCommaBrackets = new char[] { ' ', '(', ',', ')' }; + /// /// Parses a response string for content length /// @@ -885,26 +888,28 @@ private static long GetContentLengthFrom213Response(string responseString) private DateTime GetLastModifiedFrom213Response(string str) { DateTime dateTime = _lastModified; - string[] parsedList = str.Split(new char[] { ' ', '.' }); - if (parsedList.Length < 2) + Span parts = stackalloc Range[4]; + ReadOnlySpan strSpan = str; + int count = strSpan.SplitAny(parts, " ."); + if (count < 2) { return dateTime; } - string dateTimeLine = parsedList[1]; + ReadOnlySpan dateTimeLine = strSpan[parts[1]]; if (dateTimeLine.Length < 14) { return dateTime; } - int year = Convert.ToInt32(dateTimeLine.Substring(0, 4), NumberFormatInfo.InvariantInfo); - int month = Convert.ToInt16(dateTimeLine.Substring(4, 2), NumberFormatInfo.InvariantInfo); - int day = Convert.ToInt16(dateTimeLine.Substring(6, 2), NumberFormatInfo.InvariantInfo); - int hour = Convert.ToInt16(dateTimeLine.Substring(8, 2), NumberFormatInfo.InvariantInfo); - int minute = Convert.ToInt16(dateTimeLine.Substring(10, 2), NumberFormatInfo.InvariantInfo); - int second = Convert.ToInt16(dateTimeLine.Substring(12, 2), NumberFormatInfo.InvariantInfo); + int year = int.Parse(dateTimeLine.Slice(0, 4), NumberFormatInfo.InvariantInfo); + int month = short.Parse(dateTimeLine.Slice(4, 2), NumberFormatInfo.InvariantInfo); + int day = short.Parse(dateTimeLine.Slice(6, 2), NumberFormatInfo.InvariantInfo); + int hour = short.Parse(dateTimeLine.Slice(8, 2), NumberFormatInfo.InvariantInfo); + int minute = short.Parse(dateTimeLine.Slice(10, 2), NumberFormatInfo.InvariantInfo); + int second = short.Parse(dateTimeLine.Slice(12, 2), NumberFormatInfo.InvariantInfo); int millisecond = 0; - if (parsedList.Length > 2) + if (count > 2) { - millisecond = Convert.ToInt16(parsedList[2], NumberFormatInfo.InvariantInfo); + millisecond = short.Parse(strSpan[parts[2]], NumberFormatInfo.InvariantInfo); } try { @@ -941,12 +946,10 @@ private void TryUpdateResponseUri(string str, FtpWebRequest request) if (end <= start) return; - string filename = str.Substring(start, end - start); - filename = filename.TrimEnd(new char[] { ' ', '.', '\r', '\n' }); + string filename = str.AsSpan(start, end - start).TrimEnd(s_whitespaceDot).ToString(); // Do minimal escaping that we need to get a valid Uri // when combined with the baseUri - string escapedFilename; - escapedFilename = filename.Replace("%", "%25"); + string escapedFilename = filename.Replace("%", "%25"); escapedFilename = escapedFilename.Replace("#", "%23"); // help us out if the user forgot to add a slash to the directory name @@ -1022,7 +1025,7 @@ private static string GetLoginDirectory(string str) /// private static int GetPortV4(string responseString) { - string[] parsedList = responseString.Split(new char[] { ' ', '(', ',', ')' }); + string[] parsedList = responseString.Split(s_spaceCommaBrackets); // We need at least the status code and the port if (parsedList.Length <= 7) 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 168873423c0b1f..e33ffea0fa140d 100644 --- a/src/libraries/System.Net.Requests/src/System/Net/WebRequest.cs +++ b/src/libraries/System.Net.Requests/src/System/Net/WebRequest.cs @@ -513,29 +513,26 @@ public virtual Stream EndGetRequestStream(IAsyncResult asyncResult) throw NotImplemented.ByDesignWithMessage(SR.net_MethodNotImplementedException); } - public virtual Task GetRequestStreamAsync() + public virtual async Task GetRequestStreamAsync() { // Offload to a different thread to avoid blocking the caller during request submission. - // We use Task.Run rather than Task.Factory.StartNew even though StartNew would let us pass 'this' - // as a state argument to avoid the closure to capture 'this' and the associated delegate. - // This is because the task needs to call FromAsync and marshal the inner Task out, and - // Task.Run's implementation of this is sufficiently more efficient than what we can do with - // Unwrap() that it's worth it to just rely on Task.Run and accept the closure/delegate. - return Task.Run(() => - Task.Factory.FromAsync( - (callback, state) => ((WebRequest)state!).BeginGetRequestStream(callback, state), - iar => ((WebRequest)iar.AsyncState!).EndGetRequestStream(iar), - this)); - } - - public virtual Task GetResponseAsync() - { - // See comment in GetRequestStreamAsync(). Same logic applies here. - return Task.Run(() => - Task.Factory.FromAsync( - (callback, state) => ((WebRequest)state!).BeginGetResponse(callback, state), - iar => ((WebRequest)iar.AsyncState!).EndGetResponse(iar), - this)); + await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); + + return await Task.Factory.FromAsync( + (callback, state) => ((WebRequest)state!).BeginGetRequestStream(callback, state), + iar => ((WebRequest)iar.AsyncState!).EndGetRequestStream(iar), + this).ConfigureAwait(false); + } + + public virtual async Task GetResponseAsync() + { + // Offload to a different thread to avoid blocking the caller during request submission. + await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); + + return await Task.Factory.FromAsync( + (callback, state) => ((WebRequest)state!).BeginGetResponse(callback, state), + iar => ((WebRequest)iar.AsyncState!).EndGetResponse(iar), + this).ConfigureAwait(false); } public virtual void Abort() 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 6c10d2c5c3eec6..6b724c9a1709cb 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 @@ -2412,11 +2412,7 @@ private static int EndSendReceive(IAsyncResult asyncResult, out SocketError erro { Task ti = TaskToAsyncResult.Unwrap(asyncResult); - if (!ti.IsCompleted) - { - // TODO https://github.com/dotnet/runtime/issues/17148: Wait without throwing - ((IAsyncResult)ti).AsyncWaitHandle.WaitOne(); - } + ((Task)ti).ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing).GetAwaiter().GetResult(); if (ti.IsCompletedSuccessfully) { diff --git a/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/BrowserWebSockets/BrowserWebSocket.cs b/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/BrowserWebSockets/BrowserWebSocket.cs index 42dacbb7c1b997..a4b8e562eb0d01 100644 --- a/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/BrowserWebSockets/BrowserWebSocket.cs +++ b/src/libraries/System.Net.WebSockets.Client/src/System/Net/WebSockets/BrowserWebSockets/BrowserWebSocket.cs @@ -190,9 +190,8 @@ private async Task ConnectAsyncCore(Uri uri, List? requestedSubProtocols _innerWebSocket = BrowserInterop.UnsafeCreate(uri.ToString(), subProtocols, responseStatusHandle.Value, onClose); var openTask = BrowserInterop.WebSocketOpen(_innerWebSocket); - var wrappedTask = CancelationHelper(openTask!, cancellationToken, _state); - await wrappedTask.ConfigureAwait(true); + await CancelationHelper(openTask!, cancellationToken, _state).ConfigureAwait(true); if (State == WebSocketState.Connecting) { _state = WebSocketState.Open; @@ -224,13 +223,8 @@ private async Task SendAsyncCore(ArraySegment buffer, WebSocketMessageType // return synchronously return; } - var wrappedTask = CancelationHelper(sendTask, cancellationToken, _state); - await wrappedTask.ConfigureAwait(true); - } - catch (OperationCanceledException) - { - throw; + await CancelationHelper(sendTask, cancellationToken, _state).ConfigureAwait(true); } catch (JSException ex) { @@ -256,16 +250,11 @@ private async Task ReceiveAsyncCore(ArraySegment b return ConvertResponse(); } - var wrappedTask = CancelationHelper(receiveTask, cancellationToken, _state); - await wrappedTask.ConfigureAwait(true); + await CancelationHelper(receiveTask, cancellationToken, _state).ConfigureAwait(true); return ConvertResponse(); } } - catch (OperationCanceledException) - { - throw; - } catch (JSException ex) { if (ex.Message.StartsWith("InvalidState:")) @@ -298,8 +287,7 @@ private async Task CloseAsyncCore(WebSocketCloseStatus closeStatus, string? stat var closeTask = BrowserInterop.WebSocketClose(_innerWebSocket!, (int)closeStatus, statusDescription, waitForCloseReceived); if (closeTask != null) { - var wrappedTask = CancelationHelper(closeTask, cancellationToken, _state); - await wrappedTask.ConfigureAwait(true); + await CancelationHelper(closeTask, cancellationToken, _state).ConfigureAwait(true); } var state = State; diff --git a/src/libraries/System.Private.CoreLib/src/CompatibilitySuppressions.xml b/src/libraries/System.Private.CoreLib/src/CompatibilitySuppressions.xml index 3f7209cd1a5d5f..6ee3efba01f6e4 100644 --- a/src/libraries/System.Private.CoreLib/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Private.CoreLib/src/CompatibilitySuppressions.xml @@ -17,8 +17,4 @@ CP0002 F:System.Resources.ResourceSet.Reader - - CP0014 - M:System.Runtime.InteropServices.Marshal.CreateWrapperOfType(System.Object,System.Type)->object?:[T:System.Diagnostics.CodeAnalysis.NotNullIfNotNullAttribute] - \ No newline at end of file diff --git a/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.NoX86Intrinsics.xm b/src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Substitutions.NoX86Intrinsics.xm new file mode 100644 index 00000000000000..e69de29bb2d1d6 diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index 90536bdba39bb1..dbc8fca4de5679 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -172,18 +172,27 @@ Default principal object cannot be set twice. - - Ambiguous implementation found. - Cannot access member. Attempted to read or write protected memory. This is often an indication that other memory is corrupt. - + + Ambiguous implementation found. + + + Multiple custom attributes of the same type '{0}' found. + + Ambiguous match found. + + Ambiguous match found for '{0}'. + + + Ambiguous match found for '{0} {1}'. + Error in the application. @@ -3299,9 +3308,6 @@ Stream is not a valid resource file. - - Multiple custom attributes of the same type found. - An Int32 must be provided for the filter criteria. @@ -3503,6 +3509,9 @@ The tasks array included at least one null element. + + Task<TResult>.ConfigureAwait does not support ConfigureAwaitOptions.SuppressThrowing. To suppress throwing, instead cast the Task<TResult> to its base class Task and await that with SuppressThrowing. + A task was canceled. 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 2bd91205377528..d80ad76e071a21 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 @@ -371,7 +371,6 @@ - @@ -1175,6 +1174,7 @@ + @@ -1256,9 +1256,6 @@ - - Common\Interop\Interop.Normalization.cs - Common\Interop\Interop.CompareInfo.cs @@ -1274,7 +1271,7 @@ Common\Interop\Interop.Collation.cs - + Common\Interop\Interop.Collation.OSX.cs @@ -2617,4 +2614,4 @@ - \ No newline at end of file + diff --git a/src/libraries/System.Private.CoreLib/src/System/AccessViolationException.cs b/src/libraries/System.Private.CoreLib/src/System/AccessViolationException.cs index 9c98879b7fbe23..fbecb11272f516 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AccessViolationException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AccessViolationException.cs @@ -11,12 +11,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class AccessViolationException : SystemException { public AccessViolationException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Activator.RuntimeType.cs b/src/libraries/System.Private.CoreLib/src/System/Activator.RuntimeType.cs index b876ef34dcf766..87c163a176e8e7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Activator.RuntimeType.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Activator.RuntimeType.cs @@ -7,6 +7,8 @@ using System.Runtime.Loader; using System.Runtime.Remoting; using System.Threading; +using System.Runtime.CompilerServices; +using System.Security; namespace System { @@ -20,7 +22,7 @@ public static partial class Activator { ArgumentNullException.ThrowIfNull(type); - if (type is System.Reflection.Emit.TypeBuilder) + if (type is Reflection.Emit.TypeBuilder) throw new NotSupportedException(SR.NotSupported_CreateInstanceWithTypeBuilder); // If they didn't specify a lookup, then we will provide the default lookup. @@ -37,7 +39,7 @@ public static partial class Activator return rt.CreateInstanceImpl(bindingAttr, binder, args, culture); } - [System.Security.DynamicSecurityMethod] + [DynamicSecurityMethod] [RequiresUnreferencedCode("Type and its constructor could be removed")] public static ObjectHandle? CreateInstance(string assemblyName, string typeName) { @@ -53,7 +55,7 @@ public static partial class Activator ref stackMark); } - [System.Security.DynamicSecurityMethod] + [DynamicSecurityMethod] [RequiresUnreferencedCode("Type and its constructor could be removed")] public static ObjectHandle? CreateInstance(string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, CultureInfo? culture, object?[]? activationAttributes) { @@ -69,7 +71,7 @@ public static partial class Activator ref stackMark); } - [System.Security.DynamicSecurityMethod] + [DynamicSecurityMethod] [RequiresUnreferencedCode("Type and its constructor could be removed")] public static ObjectHandle? CreateInstance(string assemblyName, string typeName, object?[]? activationAttributes) { @@ -132,7 +134,7 @@ public static partial class Activator return o != null ? new ObjectHandle(o) : null; } - [System.Runtime.CompilerServices.Intrinsic] + [Intrinsic] public static T CreateInstance<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]T>() { return (T)((RuntimeType)typeof(T)).CreateInstanceOfT()!; diff --git a/src/libraries/System.Private.CoreLib/src/System/AggregateException.cs b/src/libraries/System.Private.CoreLib/src/System/AggregateException.cs index cedfd4916fa5f2..355b0b66204d91 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AggregateException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AggregateException.cs @@ -6,6 +6,7 @@ using System.ComponentModel; using System.Diagnostics; using System.Globalization; +using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Runtime.Serialization; using System.Text; @@ -19,7 +20,7 @@ namespace System /// [Serializable] [DebuggerDisplay("Count = {InnerExceptionCount}")] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class AggregateException : Exception { private readonly Exception[] _innerExceptions; // Complete set of exceptions. @@ -50,7 +51,7 @@ public AggregateException(string? message) /// /// The error message that explains the reason for the exception. /// The exception that is the cause of the current exception. - /// The argument + /// The argument /// is null. public AggregateException(string? message, Exception innerException) : base(message, innerException) @@ -65,9 +66,9 @@ public AggregateException(string? message, Exception innerException) /// references to the inner exceptions that are the cause of this exception. /// /// The exceptions that are the cause of the current exception. - /// The argument + /// The argument /// is null. - /// An element of is + /// An element of is /// null. public AggregateException(IEnumerable innerExceptions) : this(SR.AggregateException_ctor_DefaultMessage, innerExceptions ?? throw new ArgumentNullException(nameof(innerExceptions))) @@ -79,9 +80,9 @@ public AggregateException(IEnumerable innerExceptions) : /// references to the inner exceptions that are the cause of this exception. /// /// The exceptions that are the cause of the current exception. - /// The argument + /// The argument /// is null. - /// An element of is + /// An element of is /// null. public AggregateException(params Exception[] innerExceptions) : this(SR.AggregateException_ctor_DefaultMessage, innerExceptions ?? throw new ArgumentNullException(nameof(innerExceptions))) @@ -94,9 +95,9 @@ public AggregateException(params Exception[] innerExceptions) : /// /// The error message that explains the reason for the exception. /// The exceptions that are the cause of the current exception. - /// The argument + /// The argument /// is null. - /// An element of is + /// An element of is /// null. public AggregateException(string? message, IEnumerable innerExceptions) : this(message, new List(innerExceptions ?? throw new ArgumentNullException(nameof(innerExceptions))).ToArray(), cloneExceptions: false) @@ -109,9 +110,9 @@ public AggregateException(string? message, IEnumerable innerException /// /// The error message that explains the reason for the exception. /// The exceptions that are the cause of the current exception. - /// The argument + /// The argument /// is null. - /// An element of is + /// An element of is /// null. public AggregateException(string? message, params Exception[] innerExceptions) : this(message, innerExceptions ?? throw new ArgumentNullException(nameof(innerExceptions)), cloneExceptions: true) @@ -141,9 +142,9 @@ private AggregateException(string? message, Exception[] innerExceptions, bool cl /// /// Information about the exceptions that are the cause of the current exception. /// - /// The argument + /// The argument /// is null. - /// An element of is + /// An element of is /// null. internal AggregateException(List innerExceptionInfos) : this(SR.AggregateException_ctor_DefaultMessage, innerExceptionInfos) @@ -159,9 +160,9 @@ internal AggregateException(List innerExceptionInfos) : /// /// Information about the exceptions that are the cause of the current exception. /// - /// The argument + /// The argument /// is null. - /// An element of is + /// An element of is /// null. internal AggregateException(string message, List innerExceptionInfos) : base(message, innerExceptionInfos.Count != 0 ? innerExceptionInfos[0].SourceException : null) @@ -178,12 +179,12 @@ internal AggregateException(string message, List innerExc /// /// Initializes a new instance of the class with serialized data. /// - /// The that holds + /// The that holds /// the serialized object data about the exception being thrown. - /// The that + /// The that /// contains contextual information about the source or destination. - /// The argument is null. - /// The exception could not be deserialized correctly. + /// The argument is null. + /// The exception could not be deserialized correctly. [Obsolete(Obsoletions.LegacyFormatterImplMessage, DiagnosticId = Obsoletions.LegacyFormatterImplDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] [EditorBrowsable(EditorBrowsableState.Never)] protected AggregateException(SerializationInfo info, StreamingContext context) : @@ -199,14 +200,14 @@ protected AggregateException(SerializationInfo info, StreamingContext context) : } /// - /// Sets the with information about + /// Sets the with information about /// the exception. /// - /// The that holds + /// The that holds /// the serialized object data about the exception being thrown. - /// The that + /// The that /// contains contextual information about the source or destination. - /// The argument is null. + /// The argument is null. [Obsolete(Obsoletions.LegacyFormatterImplMessage, DiagnosticId = Obsoletions.LegacyFormatterImplDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] [EditorBrowsable(EditorBrowsableState.Never)] public override void GetObjectData(SerializationInfo info, StreamingContext context) @@ -217,7 +218,7 @@ public override void GetObjectData(SerializationInfo info, StreamingContext cont } /// - /// Returns the that is the root cause of this exception. + /// Returns the that is the root cause of this exception. /// public override Exception GetBaseException() { @@ -235,22 +236,22 @@ public override Exception GetBaseException() } /// - /// Gets a read-only collection of the instances that caused the + /// Gets a read-only collection of the instances that caused the /// current exception. /// public ReadOnlyCollection InnerExceptions => _rocView ??= new ReadOnlyCollection(_innerExceptions); /// - /// Invokes a handler on each contained by this contained by this . /// /// The predicate to execute for each exception. The predicate accepts as an - /// argument the to be processed and returns a Boolean to indicate + /// argument the to be processed and returns a Boolean to indicate /// whether the exception was handled. /// /// Each invocation of the returns true or false to indicate whether the - /// was handled. After all invocations, if any exceptions went + /// was handled. After all invocations, if any exceptions went /// unhandled, all unhandled exceptions will be put into a new /// which will be thrown. Otherwise, the method simply returns. If any /// invocations of the throws an exception, it will halt the processing @@ -258,7 +259,7 @@ public override Exception GetBaseException() /// /// An exception contained by this was not handled. - /// The argument is + /// The argument is /// null. public void Handle(Func predicate) { diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs index 534922c8c24f37..9023a33944b2f9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.cs @@ -15,7 +15,11 @@ namespace System { public static partial class AppContext { - private static Dictionary? s_dataStore; + private static Dictionary? s_dataStore +#if NATIVEAOT + = InitializeDataStore() +#endif + ; private static Dictionary? s_switches; private static string? s_defaultBaseDirectory; diff --git a/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs b/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs index df8f6c5915e0b4..4cac32a376dd0f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppDomain.cs @@ -281,7 +281,7 @@ public void SetThreadPrincipal(IPrincipal principal) } [RequiresUnreferencedCode("Type and its constructor could be removed")] - public ObjectHandle? CreateInstance(string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes) + public ObjectHandle? CreateInstance(string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, Globalization.CultureInfo? culture, object?[]? activationAttributes) { ArgumentNullException.ThrowIfNull(assemblyName); @@ -311,7 +311,7 @@ public void SetThreadPrincipal(IPrincipal principal) } [RequiresUnreferencedCode("Type and its constructor could be removed")] - public object? CreateInstanceAndUnwrap(string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes) + public object? CreateInstanceAndUnwrap(string assemblyName, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, Globalization.CultureInfo? culture, object?[]? activationAttributes) { ObjectHandle? oh = CreateInstance(assemblyName, typeName, @@ -338,7 +338,7 @@ public void SetThreadPrincipal(IPrincipal principal) } [RequiresUnreferencedCode("Type and its constructor could be removed")] - public ObjectHandle? CreateInstanceFrom(string assemblyFile, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes) + public ObjectHandle? CreateInstanceFrom(string assemblyFile, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, Globalization.CultureInfo? culture, object?[]? activationAttributes) { return Activator.CreateInstanceFrom(assemblyFile, typeName, @@ -364,7 +364,7 @@ public void SetThreadPrincipal(IPrincipal principal) } [RequiresUnreferencedCode("Type and its constructor could be removed")] - public object? CreateInstanceFromAndUnwrap(string assemblyFile, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, System.Globalization.CultureInfo? culture, object?[]? activationAttributes) + public object? CreateInstanceFromAndUnwrap(string assemblyFile, string typeName, bool ignoreCase, BindingFlags bindingAttr, Binder? binder, object?[]? args, Globalization.CultureInfo? culture, object?[]? activationAttributes) { ObjectHandle? oh = CreateInstanceFrom(assemblyFile, typeName, diff --git a/src/libraries/System.Private.CoreLib/src/System/AppDomainUnloadedException.cs b/src/libraries/System.Private.CoreLib/src/System/AppDomainUnloadedException.cs index cca4a77821de0b..9b00bce65beb21 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppDomainUnloadedException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppDomainUnloadedException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class AppDomainUnloadedException : SystemException { public AppDomainUnloadedException() diff --git a/src/libraries/System.Private.CoreLib/src/System/ApplicationException.cs b/src/libraries/System.Private.CoreLib/src/System/ApplicationException.cs index 230f9bbd09bfee..d0d7d8c81ad378 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ApplicationException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ApplicationException.cs @@ -12,6 +12,7 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System @@ -23,7 +24,7 @@ namespace System // ApplicationException extends but adds no new functionality to // RecoverableException. [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class ApplicationException : Exception { // Creates a new ApplicationException with its message string set to diff --git a/src/libraries/System.Private.CoreLib/src/System/ArgumentException.cs b/src/libraries/System.Private.CoreLib/src/System/ArgumentException.cs index 5265a299b62c9b..a46db753d8ca1c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ArgumentException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ArgumentException.cs @@ -21,7 +21,7 @@ namespace System // the contract of the method. Ideally it should give a meaningful error // message describing what was wrong and which parameter is incorrect. [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class ArgumentException : SystemException { private readonly string? _paramName; @@ -97,7 +97,7 @@ public override string Message private void SetMessageField() { - if (_message == null && HResult == System.HResults.COR_E_ARGUMENT) + if (_message == null && HResult == HResults.COR_E_ARGUMENT) { _message = SR.Arg_ArgumentException; } diff --git a/src/libraries/System.Private.CoreLib/src/System/ArgumentNullException.cs b/src/libraries/System.Private.CoreLib/src/System/ArgumentNullException.cs index fb86d3164dd745..0b0977f977e26e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ArgumentNullException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ArgumentNullException.cs @@ -20,7 +20,7 @@ namespace System // The ArgumentException is thrown when an argument // is null when it shouldn't be. [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class ArgumentNullException : ArgumentException { // Creates a new ArgumentNullException with its message diff --git a/src/libraries/System.Private.CoreLib/src/System/ArgumentOutOfRangeException.cs b/src/libraries/System.Private.CoreLib/src/System/ArgumentOutOfRangeException.cs index 03f895d5d2b249..45ae63f81cfe65 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ArgumentOutOfRangeException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ArgumentOutOfRangeException.cs @@ -22,7 +22,7 @@ namespace System // The ArgumentOutOfRangeException is thrown when an argument // is outside the legal range for that argument. [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class ArgumentOutOfRangeException : ArgumentException { private readonly object? _actualValue; diff --git a/src/libraries/System.Private.CoreLib/src/System/ArithmeticException.cs b/src/libraries/System.Private.CoreLib/src/System/ArithmeticException.cs index fcac02874fb03a..923f16fd63dc69 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ArithmeticException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ArithmeticException.cs @@ -11,6 +11,7 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System @@ -18,7 +19,7 @@ namespace System // The ArithmeticException is thrown when overflow or underflow // occurs. [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class ArithmeticException : SystemException { // Creates a new ArithmeticException with its message string set to diff --git a/src/libraries/System.Private.CoreLib/src/System/Array.cs b/src/libraries/System.Private.CoreLib/src/System/Array.cs index 78ca760bcd6206..313b064fc9e676 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Array.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Array.cs @@ -17,7 +17,7 @@ namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public abstract partial class Array : ICloneable, IList, IStructuralComparable, IStructuralEquatable { // This is the threshold where Introspective sort switches to Insertion sort. @@ -61,7 +61,7 @@ public static void Resize([NotNull] ref T[]? array, int newSize) // other way around), we can use Buffer.Memmove here. T[] newArray = new T[newSize]; - Buffer.Memmove( + Buffer.Memmove( ref MemoryMarshal.GetArrayDataReference(newArray), ref MemoryMarshal.GetArrayDataReference(larray), (uint)Math.Min(newSize, larray.Length)); @@ -204,7 +204,7 @@ public static Array CreateInstance(Type elementType, params long[] lengths) intLengths[i] = ilen; } - return Array.CreateInstance(elementType, intLengths); + return CreateInstance(elementType, intLengths); } public static void Copy(Array sourceArray, Array destinationArray, long length) @@ -533,17 +533,17 @@ int IList.Add(object? value) bool IList.Contains(object? value) { - return Array.IndexOf(this, value) >= this.GetLowerBound(0); + return IndexOf(this, value) >= this.GetLowerBound(0); } void IList.Clear() { - Array.Clear(this); + Clear(this); } int IList.IndexOf(object? value) { - return Array.IndexOf(this, value); + return IndexOf(this, value); } void IList.Insert(int index, object? value) @@ -605,7 +605,7 @@ bool IStructuralEquatable.Equals(object? other, IEqualityComparer comparer) return false; } - if (object.ReferenceEquals(this, other)) + if (ReferenceEquals(this, other)) { return true; } @@ -870,22 +870,22 @@ public static int BinarySearch(T[] array, T value) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - return BinarySearch(array, 0, array.Length, value, null); + return BinarySearch(array, 0, array.Length, value, null); } - public static int BinarySearch(T[] array, T value, System.Collections.Generic.IComparer? comparer) + public static int BinarySearch(T[] array, T value, IComparer? comparer) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - return BinarySearch(array, 0, array.Length, value, comparer); + return BinarySearch(array, 0, array.Length, value, comparer); } public static int BinarySearch(T[] array, int index, int length, T value) { - return BinarySearch(array, index, length, value, null); + return BinarySearch(array, index, length, value, null); } - public static int BinarySearch(T[] array, int index, int length, T value, System.Collections.Generic.IComparer? comparer) + public static int BinarySearch(T[] array, int index, int length, T value, IComparer? comparer) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -932,7 +932,7 @@ public void CopyTo(Array array, int index) if (array != null && array.Rank != 1) ThrowHelper.ThrowArgumentException(ExceptionResource.Arg_RankMultiDimNotSupported); // Note: Array.Copy throws a RankException and we want a consistent ArgumentException for all the IList CopyTo methods. - Array.Copy(this, GetLowerBound(0), array!, index, Length); + Copy(this, GetLowerBound(0), array!, index, Length); } public void CopyTo(Array array, long index) @@ -958,7 +958,7 @@ public static T[] Empty() public static bool Exists(T[] array, Predicate match) { - return Array.FindIndex(array, match) != -1; + return FindIndex(array, match) != -1; } public static void Fill(T[] array, T value) @@ -2015,34 +2015,34 @@ public static void Sort(TKey[] keys, TValue[]? items) { if (keys == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys); - Sort(keys, items, 0, keys.Length, null); + Sort(keys, items, 0, keys.Length, null); } public static void Sort(T[] array, int index, int length) { - Sort(array, index, length, null); + Sort(array, index, length, null); } public static void Sort(TKey[] keys, TValue[]? items, int index, int length) { - Sort(keys, items, index, length, null); + Sort(keys, items, index, length, null); } - public static void Sort(T[] array, System.Collections.Generic.IComparer? comparer) + public static void Sort(T[] array, IComparer? comparer) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); - Sort(array, 0, array.Length, comparer); + Sort(array, 0, array.Length, comparer); } - public static void Sort(TKey[] keys, TValue[]? items, System.Collections.Generic.IComparer? comparer) + public static void Sort(TKey[] keys, TValue[]? items, IComparer? comparer) { if (keys == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys); - Sort(keys, items, 0, keys.Length, comparer); + Sort(keys, items, 0, keys.Length, comparer); } - public static void Sort(T[] array, int index, int length, System.Collections.Generic.IComparer? comparer) + public static void Sort(T[] array, int index, int length, IComparer? comparer) { if (array == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); @@ -2060,7 +2060,7 @@ public static void Sort(T[] array, int index, int length, System.Collections. } } - public static void Sort(TKey[] keys, TValue[]? items, int index, int length, System.Collections.Generic.IComparer? comparer) + public static void Sort(TKey[] keys, TValue[]? items, int index, int length, IComparer? comparer) { if (keys == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.keys); @@ -2075,7 +2075,7 @@ public static void Sort(TKey[] keys, TValue[]? items, int index, i { if (items == null) { - Sort(keys, index, length, comparer); + Sort(keys, index, length, comparer); return; } diff --git a/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs b/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs index 45fe8fdee166aa..bbd18b6b0814c9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ArraySegment.cs @@ -16,6 +16,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; namespace System { @@ -25,7 +26,7 @@ namespace System // three fields from an ArraySegment may not see the same ArraySegment from one call to another // (ie, users could assign a new value to the old location). [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] #pragma warning disable CA1066 // adding IEquatable implementation could change semantics of code like that in xunit that queries for IEquatable vs enumerating contents public readonly struct ArraySegment : IList, IReadOnlyList #pragma warning restore CA1066 @@ -203,7 +204,7 @@ int IList.IndexOf(T item) { ThrowInvalidOperationIfDefault(); - int index = System.Array.IndexOf(_array!, item, _offset, _count); + int index = System.Array.IndexOf(_array!, item, _offset, _count); Debug.Assert(index < 0 || (index >= _offset && index < _offset + _count)); @@ -244,7 +245,7 @@ bool ICollection.Contains(T item) { ThrowInvalidOperationIfDefault(); - int index = System.Array.IndexOf(_array!, item, _offset, _count); + int index = System.Array.IndexOf(_array!, item, _offset, _count); Debug.Assert(index < 0 || (index >= _offset && index < _offset + _count)); diff --git a/src/libraries/System.Private.CoreLib/src/System/ArrayTypeMismatchException.cs b/src/libraries/System.Private.CoreLib/src/System/ArrayTypeMismatchException.cs index fb5e015403b1b3..b709adb3ea37c0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ArrayTypeMismatchException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ArrayTypeMismatchException.cs @@ -11,6 +11,7 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System @@ -18,7 +19,7 @@ namespace System // The ArrayMismatchException is thrown when an attempt to store // an object of the wrong type within an array occurs. [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class ArrayTypeMismatchException : SystemException { // Creates a new ArrayMismatchException with its message string set to diff --git a/src/libraries/System.Private.CoreLib/src/System/Attribute.cs b/src/libraries/System.Private.CoreLib/src/System/Attribute.cs index d9e2e0e43dfd07..ed55359f76cfc0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Attribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Attribute.cs @@ -4,12 +4,13 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Reflection; +using System.Runtime.CompilerServices; namespace System { [AttributeUsage(AttributeTargets.All, Inherited = true, AllowMultiple = false)] [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public abstract partial class Attribute { protected Attribute() { } diff --git a/src/libraries/System.Private.CoreLib/src/System/BadImageFormatException.cs b/src/libraries/System.Private.CoreLib/src/System/BadImageFormatException.cs index a6ce855ba7b368..ff85427170389d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/BadImageFormatException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/BadImageFormatException.cs @@ -12,12 +12,13 @@ using System.ComponentModel; using System.IO; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public partial class BadImageFormatException : SystemException { private readonly string? _fileName; // The name of the corrupt PE file. diff --git a/src/libraries/System.Private.CoreLib/src/System/Boolean.cs b/src/libraries/System.Private.CoreLib/src/System/Boolean.cs index 358d7c8db3acc4..3a51c7a67fccb8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Boolean.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Boolean.cs @@ -106,7 +106,7 @@ public bool TryFormat(Span destination, out int charsWritten) if (destination.Length > 3) { ulong true_val = BitConverter.IsLittleEndian ? 0x65007500720054ul : 0x54007200750065ul; // "True" - MemoryMarshal.Write(MemoryMarshal.AsBytes(destination), ref true_val); + MemoryMarshal.Write(MemoryMarshal.AsBytes(destination), ref true_val); charsWritten = 4; return true; } @@ -116,7 +116,7 @@ public bool TryFormat(Span destination, out int charsWritten) if (destination.Length > 4) { ulong fals_val = BitConverter.IsLittleEndian ? 0x73006C00610046ul : 0x460061006C0073ul; // "Fals" - MemoryMarshal.Write(MemoryMarshal.AsBytes(destination), ref fals_val); + MemoryMarshal.Write(MemoryMarshal.AsBytes(destination), ref fals_val); destination[4] = 'e'; charsWritten = 5; return true; diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffer.cs b/src/libraries/System.Private.CoreLib/src/System/Buffer.cs index f343c6e4e8b0b3..683388c96644a5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffer.cs @@ -85,7 +85,7 @@ public static byte GetByte(Array array, int index) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); } - return Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), index); + return Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), index); } public static void SetByte(Array array, int index, byte value) @@ -96,7 +96,7 @@ public static void SetByte(Array array, int index, byte value) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.index); } - Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), index) = value; + Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(array), index) = value; } // The attributes on this method are chosen for best JIT performance. diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/MemoryManager.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/MemoryManager.cs index 6603959390895e..b0eeaf22663161 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/MemoryManager.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/MemoryManager.cs @@ -6,12 +6,12 @@ namespace System.Buffers { /// - /// Manager of that provides the implementation. + /// Manager of that provides the implementation. /// public abstract class MemoryManager : IMemoryOwner, IPinnable { /// - /// Returns a . + /// Returns a . /// public virtual Memory Memory => new Memory(this, GetSpan().Length); @@ -32,14 +32,14 @@ public abstract class MemoryManager : IMemoryOwner, IPinnable public abstract void Unpin(); /// - /// Returns a for the current . + /// Returns a for the current . /// /// The element count in the memory, starting at offset 0. [MethodImpl(MethodImplOptions.AggressiveInlining)] protected Memory CreateMemory(int length) => new Memory(this, length); /// - /// Returns a for the current . + /// Returns a for the current . /// /// The offset to the element which the returned memory starts at. /// The element count in the memory, starting at element offset . 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 956562623785d5..060da500a3a27b 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 @@ -311,7 +311,7 @@ static OperationStatus InvalidDataFallback(ReadOnlySpan utf8, Span b /// /// Returns the maximum length (in bytes) of the result if you were to decode base 64 encoded text within a byte span of size "length". /// - /// + /// /// Thrown when the specified is less than 0. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Encoder.cs b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Encoder.cs index c0d03fa2d867dc..077dbde6f00e1c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Encoder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Encoder.cs @@ -144,7 +144,7 @@ public static unsafe OperationStatus EncodeToUtf8(ReadOnlySpan bytes, Span /// /// Returns the maximum length (in bytes) of the result if you were to encode binary data within a byte span of size "length". /// - /// + /// /// Thrown when the specified is less than 0 or larger than 1610612733 (since encode inflates the data by 4/3). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/libraries/System.Private.CoreLib/src/System/CannotUnloadAppDomainException.cs b/src/libraries/System.Private.CoreLib/src/System/CannotUnloadAppDomainException.cs index 4bc63d4414f5d9..d23f947639f4d2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/CannotUnloadAppDomainException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/CannotUnloadAppDomainException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class CannotUnloadAppDomainException : SystemException { public CannotUnloadAppDomainException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Char.cs b/src/libraries/System.Private.CoreLib/src/System/Char.cs index bac465382d0045..31998153de572d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Char.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Char.cs @@ -163,12 +163,12 @@ public int CompareTo(char value) // Overrides System.Object.ToString. public override string ToString() { - return char.ToString(m_value); + return ToString(m_value); } public string ToString(IFormatProvider? provider) { - return char.ToString(m_value); + return ToString(m_value); } // diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/ArrayList.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/ArrayList.cs index ec06c1e8dc20c2..9be595762266a3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/ArrayList.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/ArrayList.cs @@ -13,6 +13,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; namespace System.Collections { @@ -22,10 +23,10 @@ namespace System.Collections // of the ArrayList is automatically increased as required by reallocating the // internal array. // - [DebuggerTypeProxy(typeof(System.Collections.ArrayList.ArrayListDebugView))] + [DebuggerTypeProxy(typeof(ArrayListDebugView))] [DebuggerDisplay("Count = {Count}")] [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class ArrayList : IList, ICloneable { private object?[] _items; // Do not rename (binary serialization) diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Comparer.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Comparer.cs index 8c518d56c3b937..809cfdc8b02b7f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Comparer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Comparer.cs @@ -9,12 +9,13 @@ using System.ComponentModel; using System.Globalization; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Collections { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class Comparer : IComparer, ISerializable { private readonly CompareInfo _compareInfo; diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Concurrent/ConcurrentQueue.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Concurrent/ConcurrentQueue.cs index e700a1fb8a5de5..fb641fd6664f3e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Concurrent/ConcurrentQueue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Concurrent/ConcurrentQueue.cs @@ -74,7 +74,7 @@ public ConcurrentQueue() /// /// The collection whose elements are copied to the new . /// - /// The argument is null. + /// The argument is null. public ConcurrentQueue(IEnumerable collection) { if (collection == null) @@ -171,10 +171,10 @@ void ICollection.CopyTo(Array array, int index) IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this).GetEnumerator(); /// - /// Attempts to add an object to the . + /// Attempts to add an object to the . /// /// The object to add to the . The value can be a null + /// cref="IProducerConsumerCollection{T}"/>. The value can be a null /// reference (Nothing in Visual Basic) for reference types. /// /// true if the object was added successfully; otherwise, false. @@ -188,7 +188,7 @@ bool IProducerConsumerCollection.TryAdd(T item) } /// - /// Attempts to remove and return an object from the . + /// Attempts to remove and return an object from the . /// /// /// When this method returns, if the operation was successful, contains the @@ -740,7 +740,7 @@ private bool TryDequeueSlow([MaybeNullWhen(false)] out T item) /// /// /// When this method returns, contains an object from - /// the beginning of the or default(T) + /// the beginning of the or default(T) /// if the operation failed. /// /// true if and object was returned successfully; otherwise, false. diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Concurrent/IProducerConsumerCollection.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Concurrent/IProducerConsumerCollection.cs index 51eda32020915c..bcf2ae6a9285c6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Concurrent/IProducerConsumerCollection.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Concurrent/IProducerConsumerCollection.cs @@ -20,9 +20,9 @@ public interface IProducerConsumerCollection : IEnumerable, ICollection /// /// Copies the elements of the to /// an - /// , starting at a specified index. + /// , starting at a specified index. /// - /// The one-dimensional that is the destination of + /// The one-dimensional that is the destination of /// the elements copied from the . /// The array must have zero-based indexing. /// The zero-based index in at which copying @@ -46,7 +46,7 @@ public interface IProducerConsumerCollection : IEnumerable, ICollection /// The object to add to the . /// true if the object was added successfully; otherwise, false. - /// The was invalid for this collection. + /// The was invalid for this collection. bool TryAdd(T item); /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/DictionaryEntry.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/DictionaryEntry.cs index f2d52483307db2..9f2fff9a8d8c16 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/DictionaryEntry.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/DictionaryEntry.cs @@ -3,13 +3,14 @@ using System.Collections.Generic; using System.ComponentModel; +using System.Runtime.CompilerServices; namespace System.Collections { // A DictionaryEntry holds a key and a value from a dictionary. // It is returned by IDictionaryEnumerator::GetEntry(). [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public struct DictionaryEntry { private object _key; // Do not rename (binary serialization) diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Comparer.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Comparer.cs index 4151087faebae5..8c89e7c6b0edcc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Comparer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Comparer.cs @@ -116,7 +116,7 @@ public sealed partial class ObjectComparer : Comparer { public override int Compare(T? x, T? y) { - return System.Collections.Comparer.Default.Compare(x, y); + return Comparer.Default.Compare(x, y); } // Equals method for the comparer itself. 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 5291c2b6a7d00e..39770356157442 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 @@ -647,13 +647,13 @@ private bool TryInsert(TKey key, TValue value, InsertionBehavior behavior) } /// - /// A helper class containing APIs exposed through . + /// A helper class containing APIs exposed through . /// These methods are relatively niche and only used in specific scenarios, so adding them in a separate type avoids /// the additional overhead on each instantiation, especially in AOT scenarios. /// internal static class CollectionsMarshalHelper { - /// + /// public static ref TValue? GetValueRefOrAddDefault(Dictionary dictionary, TKey key, out bool exists) { // NOTE: this method is mirrored by Dictionary.TryInsert above. diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ICollection.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ICollection.cs index 895a025e89674e..1c1095f8a5cf75 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ICollection.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/ICollection.cs @@ -1,6 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if MONO +using System.Diagnostics.CodeAnalysis; +#endif + namespace System.Collections.Generic { // Base interface for all collections, defining enumerators, size, and @@ -10,7 +14,7 @@ public interface ICollection : IEnumerable int Count { #if MONO - [System.Diagnostics.CodeAnalysis.DynamicDependency(nameof(Array.InternalArray__ICollection_get_Count), typeof(Array))] + [DynamicDependency(nameof(Array.InternalArray__ICollection_get_Count), typeof(Array))] #endif get; } @@ -18,35 +22,35 @@ int Count bool IsReadOnly { #if MONO - [System.Diagnostics.CodeAnalysis.DynamicDependency(nameof(Array.InternalArray__ICollection_get_IsReadOnly), typeof(Array))] + [DynamicDependency(nameof(Array.InternalArray__ICollection_get_IsReadOnly), typeof(Array))] #endif get; } #if MONO - [System.Diagnostics.CodeAnalysis.DynamicDependency(nameof(Array.InternalArray__ICollection_Add) + "``1", typeof(Array))] + [DynamicDependency(nameof(Array.InternalArray__ICollection_Add) + "``1", typeof(Array))] #endif void Add(T item); #if MONO - [System.Diagnostics.CodeAnalysis.DynamicDependency(nameof(Array.InternalArray__ICollection_Clear), typeof(Array))] + [DynamicDependency(nameof(Array.InternalArray__ICollection_Clear), typeof(Array))] #endif void Clear(); #if MONO - [System.Diagnostics.CodeAnalysis.DynamicDependency(nameof(Array.InternalArray__ICollection_Contains) + "``1", typeof(Array))] + [DynamicDependency(nameof(Array.InternalArray__ICollection_Contains) + "``1", typeof(Array))] #endif bool Contains(T item); // CopyTo copies a collection into an Array, starting at a particular // index into the array. #if MONO - [System.Diagnostics.CodeAnalysis.DynamicDependency(nameof(Array.InternalArray__ICollection_CopyTo) + "``1", typeof(Array))] + [DynamicDependency(nameof(Array.InternalArray__ICollection_CopyTo) + "``1", typeof(Array))] #endif void CopyTo(T[] array, int arrayIndex); #if MONO - [System.Diagnostics.CodeAnalysis.DynamicDependency(nameof(Array.InternalArray__ICollection_Remove) + "``1", typeof(Array))] + [DynamicDependency(nameof(Array.InternalArray__ICollection_Remove) + "``1", typeof(Array))] #endif bool Remove(T item); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IEnumerable.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IEnumerable.cs index 683267db646b39..096f0d9dfff401 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IEnumerable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IEnumerable.cs @@ -1,6 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if MONO +using System.Diagnostics.CodeAnalysis; +#endif + namespace System.Collections.Generic { // Implement this interface if you need to support foreach semantics. @@ -9,7 +13,7 @@ public interface IEnumerable : IEnumerable // Returns an IEnumerator for this enumerable Object. The enumerator provides // a simple way to access all the contents of a collection. #if MONO - [System.Diagnostics.CodeAnalysis.DynamicDependency(nameof(Array.InternalArray__IEnumerable_GetEnumerator) + "``1 ", typeof(Array))] + [DynamicDependency(nameof(Array.InternalArray__IEnumerable_GetEnumerator) + "``1 ", typeof(Array))] #endif new IEnumerator GetEnumerator(); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IList.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IList.cs index a9c45c6d141957..f45ae823daf650 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IList.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IList.cs @@ -1,6 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if MONO +using System.Diagnostics.CodeAnalysis; +#endif + namespace System.Collections.Generic { // An IList is an ordered collection of objects. The exact ordering @@ -12,11 +16,11 @@ public interface IList : ICollection T this[int index] { #if MONO - [System.Diagnostics.CodeAnalysis.DynamicDependency(nameof(Array.InternalArray__get_Item) + "``1", typeof(Array))] + [DynamicDependency(nameof(Array.InternalArray__get_Item) + "``1", typeof(Array))] #endif get; #if MONO - [System.Diagnostics.CodeAnalysis.DynamicDependency(nameof(Array.InternalArray__set_Item) + "``1", typeof(Array))] + [DynamicDependency(nameof(Array.InternalArray__set_Item) + "``1", typeof(Array))] #endif set; } @@ -24,7 +28,7 @@ T this[int index] // Returns the index of a particular item, if it is in the list. // Returns -1 if the item isn't in the list. #if MONO - [System.Diagnostics.CodeAnalysis.DynamicDependency(nameof(Array.InternalArray__IndexOf) + "``1", typeof(Array))] + [DynamicDependency(nameof(Array.InternalArray__IndexOf) + "``1", typeof(Array))] #endif int IndexOf(T item); @@ -33,13 +37,13 @@ T this[int index] // number of elements in the list. If index equals the number // of items in the list, then value is appended to the end. #if MONO - [System.Diagnostics.CodeAnalysis.DynamicDependency(nameof(Array.InternalArray__Insert) + "``1", typeof(Array))] + [DynamicDependency(nameof(Array.InternalArray__Insert) + "``1", typeof(Array))] #endif void Insert(int index, T item); // Removes the item at position index. #if MONO - [System.Diagnostics.CodeAnalysis.DynamicDependency(nameof(Array.InternalArray__RemoveAt), typeof(Array))] + [DynamicDependency(nameof(Array.InternalArray__RemoveAt), typeof(Array))] #endif void RemoveAt(int index); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IReadOnlyCollection.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IReadOnlyCollection.cs index f8a68d268f5949..9d710a5780f7ab 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IReadOnlyCollection.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IReadOnlyCollection.cs @@ -1,6 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if MONO +using System.Diagnostics.CodeAnalysis; +#endif + namespace System.Collections.Generic { // Provides a read-only, covariant view of a generic list. @@ -9,7 +13,7 @@ public interface IReadOnlyCollection : IEnumerable int Count { #if MONO - [System.Diagnostics.CodeAnalysis.DynamicDependency(nameof(Array.InternalArray__IReadOnlyCollection_get_Count), typeof(Array))] + [DynamicDependency(nameof(Array.InternalArray__IReadOnlyCollection_get_Count), typeof(Array))] #endif get; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IReadOnlyList.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IReadOnlyList.cs index d811ae092ab34c..ab6b4356482deb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IReadOnlyList.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/IReadOnlyList.cs @@ -1,6 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if MONO +using System.Diagnostics.CodeAnalysis; +#endif + namespace System.Collections.Generic { // Provides a read-only, covariant view of a generic list. @@ -9,7 +13,7 @@ public interface IReadOnlyList : IReadOnlyCollection T this[int index] { #if MONO - [System.Diagnostics.CodeAnalysis.DynamicDependency(nameof(Array.InternalArray__IReadOnlyList_get_Item) + "``1", typeof(Array))] + [DynamicDependency(nameof(Array.InternalArray__IReadOnlyList_get_Item) + "``1", typeof(Array))] #endif get; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/KeyNotFoundException.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/KeyNotFoundException.cs index 9e3483d40b4159..f0d34db23b95df 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/KeyNotFoundException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/KeyNotFoundException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Collections.Generic { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class KeyNotFoundException : SystemException { public KeyNotFoundException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/KeyValuePair.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/KeyValuePair.cs index 61325d2058f2e6..267f9ad677e4e3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/KeyValuePair.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/KeyValuePair.cs @@ -3,6 +3,7 @@ using System.ComponentModel; using System.Diagnostics; +using System.Runtime.CompilerServices; using System.Text; namespace System.Collections.Generic @@ -23,7 +24,7 @@ internal static string PairToString(object? key, object? value) => // It is used by the IEnumerable implementation for both IDictionary // and IReadOnlyDictionary. [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public readonly struct KeyValuePair { [DebuggerBrowsable(DebuggerBrowsableState.Never)] diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs index b3c165595b7654..3766c19b71dea9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/List.cs @@ -306,7 +306,7 @@ public int BinarySearch(int index, int count, T item, IComparer? comparer) if (_size - index < count) ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen); - return Array.BinarySearch(_items, index, count, item, comparer); + return Array.BinarySearch(_items, index, count, item, comparer); } public int BinarySearch(T item) @@ -1074,7 +1074,7 @@ public void Sort(int index, int count, IComparer? comparer) if (count > 1) { - Array.Sort(_items, index, count, comparer); + Array.Sort(_items, index, count, comparer); } _version++; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs index ba27a5ed9d397c..65d09c1e116e16 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Generic/Queue.cs @@ -20,9 +20,9 @@ namespace System.Collections.Generic [DebuggerTypeProxy(typeof(QueueDebugView<>))] [DebuggerDisplay("Count = {Count}")] [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class Queue : IEnumerable, - System.Collections.ICollection, + ICollection, IReadOnlyCollection { private T[] _array; @@ -406,7 +406,7 @@ private void Grow(int capacity) // internal version number of the list to ensure that no modifications are // made to the list while an enumeration is in progress. public struct Enumerator : IEnumerator, - System.Collections.IEnumerator + IEnumerator { private readonly Queue _q; private readonly int _version; diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/Hashtable.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/Hashtable.cs index dfc019167c7d80..a46b52c7334110 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/Hashtable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/Hashtable.cs @@ -13,6 +13,7 @@ using System.ComponentModel; using System.Diagnostics; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Threading; @@ -52,10 +53,10 @@ namespace System.Collections // the Hashtable. That hash function (and the equals method on the // IEqualityComparer) would be used for all objects in the table. // - [DebuggerTypeProxy(typeof(System.Collections.Hashtable.HashtableDebugView))] + [DebuggerTypeProxy(typeof(HashtableDebugView))] [DebuggerDisplay("Count = {Count}")] [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class Hashtable : IDictionary, ISerializable, IDeserializationCallback, ICloneable { /* @@ -790,12 +791,12 @@ protected virtual int GetHash(object key) protected virtual bool KeyEquals(object? item, object key) { Debug.Assert(key != null, "key can't be null here!"); - if (object.ReferenceEquals(_buckets, item)) + if (ReferenceEquals(_buckets, item)) { return false; } - if (object.ReferenceEquals(item, key)) + if (ReferenceEquals(item, key)) return true; if (_keycomparer != null) @@ -1333,7 +1334,7 @@ public override object Clone() { lock (_table.SyncRoot) { - return Hashtable.Synchronized((Hashtable)_table.Clone()); + return Synchronized((Hashtable)_table.Clone()); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/IHashCodeProvider.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/IHashCodeProvider.cs index 6c758b937d3f0f..5554724830fe2b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/IHashCodeProvider.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/IHashCodeProvider.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; + namespace System.Collections { /// @@ -8,7 +10,7 @@ namespace System.Collections /// GetHashCode() function on Objects, providing their own hash function. /// [Obsolete("IHashCodeProvider has been deprecated. Use IEqualityComparer instead.")] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public interface IHashCodeProvider { /// Returns a hash code for the given object. diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/ListDictionaryInternal.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/ListDictionaryInternal.cs index 73d76517931b78..aff9166ee4fe32 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/ListDictionaryInternal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/ListDictionaryInternal.cs @@ -11,13 +11,15 @@ ** ===========================================================*/ +using System.Runtime.CompilerServices; + namespace System.Collections { /// This is a simple implementation of IDictionary using a singly linked list. This /// will be smaller and faster than a Hashtable if the number of elements is 10 or less. /// This should not be used if performance is important for large numbers of elements. [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] // Needs to be public to support binary serialization compatibility public class ListDictionaryInternal : IDictionary { diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/ObjectModel/Collection.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/ObjectModel/Collection.cs index 80c2cc064226b3..4c6aa24b0a4a63 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/ObjectModel/Collection.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/ObjectModel/Collection.cs @@ -3,13 +3,14 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Runtime.CompilerServices; namespace System.Collections.ObjectModel { [Serializable] [DebuggerTypeProxy(typeof(ICollectionDebugView<>))] [DebuggerDisplay("Count = {Count}")] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class Collection : IList, IList, IReadOnlyList { private readonly IList items; // Do not rename (binary serialization) diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/ObjectModel/ReadOnlyCollection.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/ObjectModel/ReadOnlyCollection.cs index 874db5fad5f47e..62e45314a1c7cf 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/ObjectModel/ReadOnlyCollection.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/ObjectModel/ReadOnlyCollection.cs @@ -3,13 +3,14 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Runtime.CompilerServices; namespace System.Collections.ObjectModel { [Serializable] [DebuggerTypeProxy(typeof(ICollectionDebugView<>))] [DebuggerDisplay("Count = {Count}")] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class ReadOnlyCollection : IList, IList, IReadOnlyList { private readonly IList list; // Do not rename (binary serialization) diff --git a/src/libraries/System.Private.CoreLib/src/System/Collections/ObjectModel/ReadOnlyDictionary.cs b/src/libraries/System.Private.CoreLib/src/System/Collections/ObjectModel/ReadOnlyDictionary.cs index d13a7198f07493..d002398922ace3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Collections/ObjectModel/ReadOnlyDictionary.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Collections/ObjectModel/ReadOnlyDictionary.cs @@ -4,13 +4,14 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; namespace System.Collections.ObjectModel { [Serializable] [DebuggerTypeProxy(typeof(IDictionaryDebugView<,>))] [DebuggerDisplay("Count = {Count}")] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class ReadOnlyDictionary : IDictionary, IDictionary, IReadOnlyDictionary where TKey : notnull { private readonly IDictionary m_dictionary; // Do not rename (binary serialization) 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 9d7ff597c9c719..e86b53d640d30f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ComponentModel/DefaultValueAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ComponentModel/DefaultValueAttribute.cs @@ -23,7 +23,7 @@ public class DefaultValueAttribute : Attribute private static object? s_convertFromInvariantString; /// - /// Initializes a new instance of the + /// 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. /// @@ -97,7 +97,7 @@ static bool TryConvertFromInvariantString( } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class using a Unicode character. /// public DefaultValueAttribute(char value) @@ -106,7 +106,7 @@ public DefaultValueAttribute(char value) } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class using an 8-bit unsigned integer. /// public DefaultValueAttribute(byte value) @@ -115,7 +115,7 @@ public DefaultValueAttribute(byte value) } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class using a 16-bit signed integer. /// public DefaultValueAttribute(short value) @@ -124,7 +124,7 @@ public DefaultValueAttribute(short value) } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class using a 32-bit signed integer. /// public DefaultValueAttribute(int value) @@ -133,7 +133,7 @@ public DefaultValueAttribute(int value) } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class using a 64-bit signed integer. /// public DefaultValueAttribute(long value) @@ -142,7 +142,7 @@ public DefaultValueAttribute(long value) } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class using a single-precision floating point number. /// public DefaultValueAttribute(float value) @@ -151,7 +151,7 @@ public DefaultValueAttribute(float value) } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class using a double-precision floating point number. /// public DefaultValueAttribute(double value) @@ -160,7 +160,7 @@ public DefaultValueAttribute(double value) } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class using a value. /// public DefaultValueAttribute(bool value) @@ -169,7 +169,7 @@ public DefaultValueAttribute(bool value) } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class using a . /// public DefaultValueAttribute(string? value) @@ -178,7 +178,7 @@ public DefaultValueAttribute(string? value) } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class. /// public DefaultValueAttribute(object? value) @@ -187,7 +187,7 @@ public DefaultValueAttribute(object? value) } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class using a value. /// [CLSCompliant(false)] @@ -197,7 +197,7 @@ public DefaultValueAttribute(sbyte value) } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class using a value. /// [CLSCompliant(false)] @@ -207,7 +207,7 @@ public DefaultValueAttribute(ushort value) } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class using a value. /// [CLSCompliant(false)] @@ -217,7 +217,7 @@ public DefaultValueAttribute(uint value) } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class using a value. /// [CLSCompliant(false)] diff --git a/src/libraries/System.Private.CoreLib/src/System/ComponentModel/Win32Exception.cs b/src/libraries/System.Private.CoreLib/src/System/ComponentModel/Win32Exception.cs index a6239139beef8d..5443127bc3030d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ComponentModel/Win32Exception.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ComponentModel/Win32Exception.cs @@ -3,6 +3,7 @@ using System.ComponentModel; using System.Globalization; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Text; @@ -13,13 +14,13 @@ namespace System.ComponentModel /// The exception that is thrown for a Win32 error code. /// [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class Win32Exception : ExternalException { private const int E_FAIL = unchecked((int)0x80004005); /// - /// Initializes a new instance of the class with the last Win32 error + /// Initializes a new instance of the class with the last Win32 error /// that occurred. /// public Win32Exception() : this(Marshal.GetLastPInvokeError()) @@ -27,13 +28,13 @@ public Win32Exception() : this(Marshal.GetLastPInvokeError()) } /// - /// Initializes a new instance of the class with the specified error. + /// Initializes a new instance of the class with the specified error. /// public Win32Exception(int error) : this(error, Marshal.GetPInvokeErrorMessage(error)) { } /// - /// Initializes a new instance of the class with the specified error and the + /// Initializes a new instance of the class with the specified error and the /// specified detailed description. /// public Win32Exception(int error, string? message) : base(message) diff --git a/src/libraries/System.Private.CoreLib/src/System/Context.cs b/src/libraries/System.Private.CoreLib/src/System/Context.cs index 49f0cf41878eda..b04815e3554ed3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Context.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Context.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System @@ -12,7 +13,7 @@ protected ContextBoundObject() { } } [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class ContextMarshalException : SystemException { public ContextMarshalException() : this(SR.Arg_ContextMarshalException, null) diff --git a/src/libraries/System.Private.CoreLib/src/System/CurrentSystemTimeZone.cs b/src/libraries/System.Private.CoreLib/src/System/CurrentSystemTimeZone.cs index 2c48513d454c87..506e457c3fb60f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/CurrentSystemTimeZone.cs +++ b/src/libraries/System.Private.CoreLib/src/System/CurrentSystemTimeZone.cs @@ -164,7 +164,7 @@ public override TimeSpan GetUtcOffset(DateTime time) } else { - return new TimeSpan(TimeZone.CalculateUtcOffset(time, GetDaylightChanges(time.Year)).Ticks + m_ticksOffset); + return new TimeSpan(CalculateUtcOffset(time, GetDaylightChanges(time.Year)).Ticks + m_ticksOffset); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/DataMisalignedException.cs b/src/libraries/System.Private.CoreLib/src/System/DataMisalignedException.cs index 9325e30e67a50e..766e877489b06a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DataMisalignedException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DataMisalignedException.cs @@ -9,12 +9,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class DataMisalignedException : SystemException { public DataMisalignedException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Decimal.cs b/src/libraries/System.Private.CoreLib/src/System/Decimal.cs index 33b7acca438a2c..b6c6c0704ace18 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Decimal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Decimal.cs @@ -1578,14 +1578,14 @@ private static bool TryConvertFromChecked(TOther value, out decimal resu [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromSaturating(TOther value, out decimal result) { - return TryConvertFrom(value, out result); + return TryConvertFrom(value, out result); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromTruncating(TOther value, out decimal result) { - return TryConvertFrom(value, out result); + return TryConvertFrom(value, out result); } private static bool TryConvertFrom(TOther value, out decimal result) @@ -1727,14 +1727,14 @@ static bool INumberBase.TryConvertToChecked(decimal value, [May [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertToSaturating(decimal value, [MaybeNullWhen(false)] out TOther result) { - return TryConvertTo(value, out result); + return TryConvertTo(value, out result); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertToTruncating(decimal value, [MaybeNullWhen(false)] out TOther result) { - return TryConvertTo(value, out result); + return TryConvertTo(value, out result); } private static bool TryConvertTo(decimal value, [MaybeNullWhen(false)] out TOther result) diff --git a/src/libraries/System.Private.CoreLib/src/System/DefaultBinder.cs b/src/libraries/System.Private.CoreLib/src/System/DefaultBinder.cs index 1a2e483ce371d0..293ecd84893802 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DefaultBinder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DefaultBinder.cs @@ -130,14 +130,14 @@ public sealed override MethodBase BindToMethod( // we are in the situation were we may be using default values. for (j = args.Length; j < par.Length - 1; j++) { - if (par[j].DefaultValue == System.DBNull.Value) + if (par[j].DefaultValue == DBNull.Value) break; } if (j != par.Length - 1) continue; - if (par[j].DefaultValue == System.DBNull.Value) + if (par[j].DefaultValue == DBNull.Value) { if (!par[j].ParameterType.IsArray) continue; @@ -354,7 +354,7 @@ public sealed override MethodBase BindToMethod( int paramArrayPos = parms.Length - 1; Array.Copy(args, objs, paramArrayPos); objs[paramArrayPos] = Array.CreateInstance(paramArrayTypes[0], args.Length - paramArrayPos); - Array.Copy(args, paramArrayPos, (System.Array)objs[paramArrayPos], 0, args.Length - paramArrayPos); + Array.Copy(args, paramArrayPos, (Array)objs[paramArrayPos], 0, args.Length - paramArrayPos); args = objs; } } @@ -383,8 +383,10 @@ public sealed override MethodBase BindToMethod( #endregion } + MethodBase bestMatch = candidates[currentMin]!; + if (ambig) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(bestMatch); // Reorder (if needed) if (names != null) @@ -395,7 +397,7 @@ public sealed override MethodBase BindToMethod( // If the parameters and the args are not the same length or there is a paramArray // then we need to create a argument array. - ParameterInfo[] parameters = candidates[currentMin]!.GetParametersNoCopy(); + ParameterInfo[] parameters = bestMatch.GetParametersNoCopy(); if (parameters.Length == args.Length) { if (paramArrayTypes[currentMin] != null) @@ -431,18 +433,18 @@ public sealed override MethodBase BindToMethod( } else { - if ((candidates[currentMin]!.CallingConvention & CallingConventions.VarArgs) == 0) + if ((bestMatch.CallingConvention & CallingConventions.VarArgs) == 0) { object[] objs = new object[parameters.Length]; int paramArrayPos = parameters.Length - 1; Array.Copy(args, objs, paramArrayPos); objs[paramArrayPos] = Array.CreateInstance(paramArrayTypes[currentMin], args.Length - paramArrayPos); - Array.Copy(args, paramArrayPos, (System.Array)objs[paramArrayPos], 0, args.Length - paramArrayPos); + Array.Copy(args, paramArrayPos, (Array)objs[paramArrayPos], 0, args.Length - paramArrayPos); args = objs; } } - return candidates[currentMin]!; + return bestMatch; } // Given a set of fields that match the base criteria, select a field. @@ -526,9 +528,10 @@ public sealed override FieldInfo BindToField(BindingFlags bindingAttr, FieldInfo } } } + FieldInfo bestMatch = candidates[currentMin]; if (ambig) - throw new AmbiguousMatchException(); - return candidates[currentMin]; + throw ThrowHelper.GetAmbiguousMatchException(bestMatch); + return bestMatch; } // Given a set of methods that match the base criteria, select a method based @@ -620,9 +623,10 @@ public sealed override FieldInfo BindToField(BindingFlags bindingAttr, FieldInfo } } } + MethodBase bestMatch = candidates[currentMin]; if (ambig) - throw new AmbiguousMatchException(); - return candidates[currentMin]; + throw ThrowHelper.GetAmbiguousMatchException(bestMatch); + return bestMatch; } // Given a set of properties that match the base criteria, select one. @@ -734,10 +738,10 @@ public sealed override FieldInfo BindToField(BindingFlags bindingAttr, FieldInfo currentMin = i; } } - + PropertyInfo bestMatch = candidates[currentMin]; if (ambig) - throw new AmbiguousMatchException(); - return candidates[currentMin]; + throw ThrowHelper.GetAmbiguousMatchException(bestMatch); + return bestMatch; } // ChangeType @@ -850,7 +854,7 @@ public sealed override void ReorderArgumentArray(ref object?[] args, object stat continue; if (bestMatch != null) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(bestMatch); bestMatch = match[i]; } @@ -1137,7 +1141,7 @@ private static int GetHierarchyDepth(Type t) // This can only happen if at least one is vararg or generic. if (currentHierarchyDepth == deepestHierarchy) { - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(methWithDeepestHierarchy!); } // Check to see if this method is on the most derived class. diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMembersAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMembersAttribute.cs index 460b57df3e52c9..45166d5259b5ff 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMembersAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/DynamicallyAccessedMembersAttribute.cs @@ -5,7 +5,7 @@ namespace System.Diagnostics.CodeAnalysis { /// /// Indicates that certain members on a specified are accessed dynamically, - /// for example through . + /// for example through . /// /// /// This allows tools to understand which members are being accessed during the execution diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/ExcludeFromCodeCoverageAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/ExcludeFromCodeCoverageAttribute.cs index fa8730a8eeb62d..181bbeee50b7cc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/ExcludeFromCodeCoverageAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/ExcludeFromCodeCoverageAttribute.cs @@ -3,7 +3,7 @@ namespace System.Diagnostics.CodeAnalysis { - [AttributeUsageAttribute(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event, Inherited = false, AllowMultiple = false)] + [AttributeUsage(AttributeTargets.Assembly | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event, Inherited = false, AllowMultiple = false)] public sealed class ExcludeFromCodeCoverageAttribute : Attribute { public ExcludeFromCodeCoverageAttribute() { } diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresDynamicCodeAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresDynamicCodeAttribute.cs index e2df463a043eb0..f6037d8660ba04 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresDynamicCodeAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresDynamicCodeAttribute.cs @@ -5,7 +5,7 @@ namespace System.Diagnostics.CodeAnalysis { /// /// Indicates that the specified method requires the ability to generate new code at runtime, - /// for example through . + /// for example through . /// /// /// This allows tools to understand which methods are unsafe to call when compiling ahead of time. diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresUnreferencedCodeAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresUnreferencedCodeAttribute.cs index 12688c1075a313..d063603281fd73 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresUnreferencedCodeAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresUnreferencedCodeAttribute.cs @@ -5,7 +5,7 @@ namespace System.Diagnostics.CodeAnalysis { /// /// Indicates that the specified method requires dynamic access to code that is not referenced - /// statically, for example through . + /// statically, for example through . /// /// /// This allows tools to understand which methods are unsafe to call when removing unreferenced diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/UnscopedRefAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/UnscopedRefAttribute.cs index cb38703a6354c0..e9b6dd1feefdfb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/UnscopedRefAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/UnscopedRefAttribute.cs @@ -27,7 +27,7 @@ namespace System.Diagnostics.CodeAnalysis /// API authors to understand the lifetime implications of applying this attribute and how it may impact their users. /// /// - [AttributeUsageAttribute( + [AttributeUsage( AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Contracts/ContractException.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Contracts/ContractException.cs index 8925fb287823d1..0446081b9ef5ff 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Contracts/ContractException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Contracts/ContractException.cs @@ -2,13 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Diagnostics.Contracts { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - // Needs to be public to support binary serialization compatibility + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] // Needs to be public to support binary serialization compatibility public sealed class ContractException : Exception { private readonly ContractFailureKind _kind; diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Contracts/Contracts.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Contracts/Contracts.cs index 61b5d424a44ba9..eec0cef494c812 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Contracts/Contracts.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Contracts/Contracts.cs @@ -217,7 +217,7 @@ public static partial class Contract /// /// Expression to assume will always be true. /// - /// At runtime this is equivalent to an . + /// At runtime this is equivalent to an . /// [Pure] [Conditional("DEBUG")] @@ -236,7 +236,7 @@ public static void Assume([DoesNotReturnIf(false)] bool condition) /// Expression to assume will always be true. /// If it is not a constant string literal, then the contract may not be understood by tools. /// - /// At runtime this is equivalent to an . + /// At runtime this is equivalent to an . /// [Pure] [Conditional("DEBUG")] @@ -511,7 +511,7 @@ public static void Invariant(bool condition, string? userMessage) /// Function that is evaluated from to - 1. /// true if returns true for all integers /// starting from to - 1. - /// + /// [Pure] public static bool ForAll(int fromInclusive, int toExclusive, Predicate predicate) { @@ -533,7 +533,7 @@ public static bool ForAll(int fromInclusive, int toExclusive, Predicate pre /// Function that is evaluated on elements from . /// true if and only if returns true for all elements in /// . - /// + /// [Pure] public static bool ForAll(IEnumerable collection, Predicate predicate) { @@ -558,7 +558,7 @@ public static bool ForAll(IEnumerable collection, Predicate predicate) /// Function that is evaluated from to - 1. /// true if returns true for any integer /// starting from to - 1. - /// + /// [Pure] public static bool Exists(int fromInclusive, int toExclusive, Predicate predicate) { @@ -579,7 +579,7 @@ public static bool Exists(int fromInclusive, int toExclusive, Predicate pre /// Function that is evaluated on elements from . /// true if and only if returns true for an element in /// . - /// + /// [Pure] public static bool Exists(IEnumerable collection, Predicate predicate) { @@ -647,7 +647,7 @@ private static void AssertMustUseRewriter(ContractFailureKind kind, string contr /// Code going through the contract rewriter never calls this method. Instead, the rewriter produced failures call /// ContractHelper.RaiseContractFailedEvent, followed by ContractHelper.TriggerFailure. /// - [System.Diagnostics.DebuggerNonUserCode] + [DebuggerNonUserCode] private static void ReportFailure(ContractFailureKind failureKind, string? userMessage, string? conditionText, Exception? innerException) { if (failureKind < ContractFailureKind.Precondition || failureKind > ContractFailureKind.Assume) @@ -685,7 +685,7 @@ public static event EventHandler? ContractFailed #endregion Failure Behavior } - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public enum ContractFailureKind { Precondition, diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/DebugProvider.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/DebugProvider.cs index 4bc93b781bf670..cd280db8d8a231 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/DebugProvider.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/DebugProvider.cs @@ -19,7 +19,7 @@ public virtual void Fail(string? message, string? detailMessage) string stackTrace; try { - stackTrace = new StackTrace(0, true).ToString(System.Diagnostics.StackTrace.TraceFormat.Normal); + stackTrace = new StackTrace(0, true).ToString(StackTrace.TraceFormat.Normal); } catch { diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackFrame.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackFrame.cs index c7aeae27684bdc..67831fc0872199 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackFrame.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackFrame.cs @@ -59,7 +59,7 @@ private void InitMembers() /// /// Constructs a StackFrame corresponding to the active stack frame. /// - [MethodImplAttribute(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.NoInlining)] public StackFrame() { InitMembers(); @@ -69,7 +69,7 @@ public StackFrame() /// /// Constructs a StackFrame corresponding to the active stack frame. /// - [MethodImplAttribute(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.NoInlining)] public StackFrame(bool needFileInfo) { InitMembers(); @@ -79,7 +79,7 @@ public StackFrame(bool needFileInfo) /// /// Constructs a StackFrame corresponding to a calling stack frame. /// - [MethodImplAttribute(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.NoInlining)] public StackFrame(int skipFrames) { InitMembers(); @@ -89,7 +89,7 @@ public StackFrame(int skipFrames) /// /// Constructs a StackFrame corresponding to a calling stack frame. /// - [MethodImplAttribute(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.NoInlining)] public StackFrame(int skipFrames, bool needFileInfo) { InitMembers(); @@ -101,7 +101,7 @@ public StackFrame(int skipFrames, bool needFileInfo) /// name and line number. Use when you don't want to use the /// debugger's line mapping logic. /// - [MethodImplAttribute(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.NoInlining)] public StackFrame(string? fileName, int lineNumber) { InitMembers(); @@ -116,7 +116,7 @@ public StackFrame(string? fileName, int lineNumber) /// name, line number and column number. Use when you don't want to /// use the debugger's line mapping logic. /// - [MethodImplAttribute(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.NoInlining)] public StackFrame(string? fileName, int lineNumber, int colNumber) { InitMembers(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs index 2b1bdfba9e1fb9..e9c7ed4beef552 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/StackTrace.cs @@ -30,7 +30,7 @@ public partial class StackTrace /// /// Constructs a stack trace from the current location. /// - [MethodImplAttribute(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.NoInlining)] public StackTrace() { InitializeForCurrentThread(METHODS_TO_SKIP, false); @@ -39,7 +39,7 @@ public StackTrace() /// /// Constructs a stack trace from the current location. /// - [MethodImplAttribute(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.NoInlining)] public StackTrace(bool fNeedFileInfo) { InitializeForCurrentThread(METHODS_TO_SKIP, fNeedFileInfo); @@ -49,7 +49,7 @@ public StackTrace(bool fNeedFileInfo) /// Constructs a stack trace from the current location, in a caller's /// frame /// - [MethodImplAttribute(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.NoInlining)] public StackTrace(int skipFrames) { ArgumentOutOfRangeException.ThrowIfNegative(skipFrames); @@ -61,7 +61,7 @@ public StackTrace(int skipFrames) /// Constructs a stack trace from the current location, in a caller's /// frame /// - [MethodImplAttribute(MethodImplOptions.NoInlining)] + [MethodImpl(MethodImplOptions.NoInlining)] public StackTrace(int skipFrames, bool fNeedFileInfo) { ArgumentOutOfRangeException.ThrowIfNegative(skipFrames); @@ -331,7 +331,7 @@ internal void ToString(TraceFormat traceFormat, StringBuilder sb) sb.Append(' '); sb.AppendFormat(CultureInfo.InvariantCulture, inFileILOffset, assemblyName, token, sf.GetILOffset()); } - catch (System.InvalidOperationException) {} + catch (InvalidOperationException) {} } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/ActivityTracker.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/ActivityTracker.cs index fdca8840819c76..1d5d086dfbfead 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/ActivityTracker.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/ActivityTracker.cs @@ -219,7 +219,7 @@ public void Enable() catch (NotImplementedException) { // send message to debugger without delay - System.Diagnostics.Debugger.Log(0, null, "Activity Enabled() called but AsyncLocals Not Supported (pre V4.6). Ignoring Enable"); + Debugger.Log(0, null, "Activity Enabled() called but AsyncLocals Not Supported (pre V4.6). Ignoring Enable"); } } } @@ -359,7 +359,7 @@ private unsafe void CreateActivityPathGuid(out Guid idRet, out int activityPathG } else { - int appDomainID = System.Threading.Thread.GetDomainID(); + int appDomainID = Thread.GetDomainID(); // We start with the appdomain number to make this unique among appdomains. activityPathGuidOffsetStart = AddIdToGuid(outPtr, activityPathGuidOffsetStart, (uint)appDomainID); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/CounterGroup.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/CounterGroup.cs index f2b5d70c974afd..71af1ba5b20973 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/CounterGroup.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/CounterGroup.cs @@ -9,7 +9,7 @@ namespace System.Diagnostics.Tracing { #if !ES_BUILD_STANDALONE #if !FEATURE_WASM_PERFTRACING - [System.Runtime.Versioning.UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("browser")] #endif #endif internal sealed class CounterGroup @@ -111,15 +111,15 @@ private void OnEventSourceCommand(object? sender, EventCommandEventArgs e) private static void EnsureEventSourceIndexAvailable(int eventSourceIndex) { Debug.Assert(Monitor.IsEntered(s_counterGroupLock)); - if (CounterGroup.s_counterGroups == null) + if (s_counterGroups == null) { - CounterGroup.s_counterGroups = new WeakReference[eventSourceIndex + 1]; + s_counterGroups = new WeakReference[eventSourceIndex + 1]; } - else if (eventSourceIndex >= CounterGroup.s_counterGroups.Length) + else if (eventSourceIndex >= s_counterGroups.Length) { WeakReference[] newCounterGroups = new WeakReference[eventSourceIndex + 1]; - Array.Copy(CounterGroup.s_counterGroups, newCounterGroups, CounterGroup.s_counterGroups.Length); - CounterGroup.s_counterGroups = newCounterGroups; + Array.Copy(s_counterGroups, newCounterGroups, s_counterGroups.Length); + s_counterGroups = newCounterGroups; } } @@ -130,11 +130,11 @@ internal static CounterGroup GetCounterGroup(EventSource eventSource) int eventSourceIndex = EventListener.EventSourceIndex(eventSource); EnsureEventSourceIndexAvailable(eventSourceIndex); Debug.Assert(s_counterGroups != null); - WeakReference weakRef = CounterGroup.s_counterGroups[eventSourceIndex]; + WeakReference weakRef = s_counterGroups[eventSourceIndex]; if (weakRef == null || !weakRef.TryGetTarget(out CounterGroup? ret)) { ret = new CounterGroup(eventSource); - CounterGroup.s_counterGroups[eventSourceIndex] = new WeakReference(ret); + s_counterGroups[eventSourceIndex] = new WeakReference(ret); } return ret; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/DiagnosticCounter.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/DiagnosticCounter.cs index d22869390c5cfc..6a4ed0b053fdc5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/DiagnosticCounter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/DiagnosticCounter.cs @@ -14,7 +14,7 @@ namespace System.Diagnostics.Tracing /// #if !ES_BUILD_STANDALONE #if !FEATURE_WASM_PERFTRACING - [System.Runtime.Versioning.UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("browser")] #endif #endif public abstract class DiagnosticCounter : IDisposable diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventCounter.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventCounter.cs index a2fa85a262be4d..c86088f9db41d7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventCounter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventCounter.cs @@ -18,7 +18,7 @@ namespace System.Diagnostics.Tracing /// #if !ES_BUILD_STANDALONE #if !FEATURE_WASM_PERFTRACING - [System.Runtime.Versioning.UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("browser")] #endif #endif public partial class EventCounter : DiagnosticCounter diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventProvider.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventProvider.cs index 5753c4a289da71..995fced70a96c2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventProvider.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/EventProvider.cs @@ -414,7 +414,7 @@ to fill the passed in ETW data descriptor. } else { - if (data is System.Enum) + if (data is Enum) { try { @@ -926,7 +926,7 @@ internal override int ActivityIdControl(Interop.Advapi32.ActivityControl Control internal override unsafe IntPtr DefineEventHandle(uint eventID, string eventName, long keywords, uint eventVersion, uint level, byte* pMetadata, uint metadataLength) { - throw new System.NotSupportedException(); + throw new NotSupportedException(); } @@ -1360,8 +1360,8 @@ private static int FindNull(byte[] buffer, int idx) int valueEnd = FindNull(data, valueIdx); if (valueEnd < data.Length) { - string key = System.Text.Encoding.UTF8.GetString(data, dataStart, keyEnd - dataStart); - string value = System.Text.Encoding.UTF8.GetString(data, valueIdx, valueEnd - valueIdx); + string key = Text.Encoding.UTF8.GetString(data, dataStart, keyEnd - dataStart); + string value = Text.Encoding.UTF8.GetString(data, valueIdx, valueEnd - valueIdx); args[key] = value; } dataStart = valueEnd + 1; 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 498c1c62b43ebd..b36fca3489f17e 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 @@ -168,6 +168,7 @@ using System.Numerics; using System.Reflection; using System.Resources; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using System.Threading; @@ -186,8 +187,8 @@ internal sealed class EventSourceAutoGenerateAttribute : Attribute /// This class is meant to be inherited by a user-defined event source in order to define a managed /// ETW provider. Please See DESIGN NOTES above for the internal architecture. /// The minimal definition of an EventSource simply specifies a number of ETW event methods that - /// call one of the EventSource.WriteEvent overloads, , - /// or to log them. This functionality + /// call one of the EventSource.WriteEvent overloads, , + /// or to log them. This functionality /// is sufficient for many users. /// /// To achieve more control over the ETW provider manifest exposed by the event source type, the @@ -197,7 +198,7 @@ internal sealed class EventSourceAutoGenerateAttribute : Attribute /// eventSource and change what filtering is done (see EventListener.EnableEvents and /// ) or cause actions to be performed by the eventSource, /// e.g. dumping a data structure (see EventSource.SendCommand and - /// ). + /// ). /// /// The eventSources can be turned on with Windows ETW controllers (e.g. logman), immediately. /// It is also possible to control and intercept the data dispatcher programmatically. See @@ -384,7 +385,7 @@ public static string GetName(Type eventSourceType) ArgumentNullException.ThrowIfNull(eventSourceType); - byte[]? manifestBytes = EventSource.CreateManifestAndDescriptors(eventSourceType, assemblyPathToIncludeInManifest, null, flags); + byte[]? manifestBytes = CreateManifestAndDescriptors(eventSourceType, assemblyPathToIncludeInManifest, null, flags); return (manifestBytes == null) ? null : Encoding.UTF8.GetString(manifestBytes, 0, manifestBytes.Length); } @@ -772,7 +773,7 @@ protected unsafe void WriteEvent(int eventId, int arg1) { if (IsEnabled()) { - EventSource.EventData* descrs = stackalloc EventSource.EventData[1]; + EventData* descrs = stackalloc EventData[1]; descrs[0].DataPointer = (IntPtr)(&arg1); descrs[0].Size = 4; descrs[0].Reserved = 0; @@ -786,7 +787,7 @@ protected unsafe void WriteEvent(int eventId, int arg1, int arg2) { if (IsEnabled()) { - EventSource.EventData* descrs = stackalloc EventSource.EventData[2]; + EventData* descrs = stackalloc EventData[2]; descrs[0].DataPointer = (IntPtr)(&arg1); descrs[0].Size = 4; descrs[0].Reserved = 0; @@ -803,7 +804,7 @@ protected unsafe void WriteEvent(int eventId, int arg1, int arg2, int arg3) { if (IsEnabled()) { - EventSource.EventData* descrs = stackalloc EventSource.EventData[3]; + EventData* descrs = stackalloc EventData[3]; descrs[0].DataPointer = (IntPtr)(&arg1); descrs[0].Size = 4; descrs[0].Reserved = 0; @@ -824,7 +825,7 @@ protected unsafe void WriteEvent(int eventId, long arg1) { if (IsEnabled()) { - EventSource.EventData* descrs = stackalloc EventSource.EventData[1]; + EventData* descrs = stackalloc EventData[1]; descrs[0].DataPointer = (IntPtr)(&arg1); descrs[0].Size = 8; descrs[0].Reserved = 0; @@ -838,7 +839,7 @@ protected unsafe void WriteEvent(int eventId, long arg1, long arg2) { if (IsEnabled()) { - EventSource.EventData* descrs = stackalloc EventSource.EventData[2]; + EventData* descrs = stackalloc EventData[2]; descrs[0].DataPointer = (IntPtr)(&arg1); descrs[0].Size = 8; descrs[0].Reserved = 0; @@ -855,7 +856,7 @@ protected unsafe void WriteEvent(int eventId, long arg1, long arg2, long arg3) { if (IsEnabled()) { - EventSource.EventData* descrs = stackalloc EventSource.EventData[3]; + EventData* descrs = stackalloc EventData[3]; descrs[0].DataPointer = (IntPtr)(&arg1); descrs[0].Size = 8; descrs[0].Reserved = 0; @@ -879,7 +880,7 @@ protected unsafe void WriteEvent(int eventId, string? arg1) arg1 ??= ""; fixed (char* string1Bytes = arg1) { - EventSource.EventData* descrs = stackalloc EventSource.EventData[1]; + EventData* descrs = stackalloc EventData[1]; descrs[0].DataPointer = (IntPtr)string1Bytes; descrs[0].Size = ((arg1.Length + 1) * 2); descrs[0].Reserved = 0; @@ -899,7 +900,7 @@ protected unsafe void WriteEvent(int eventId, string? arg1, string? arg2) fixed (char* string1Bytes = arg1) fixed (char* string2Bytes = arg2) { - EventSource.EventData* descrs = stackalloc EventSource.EventData[2]; + EventData* descrs = stackalloc EventData[2]; descrs[0].DataPointer = (IntPtr)string1Bytes; descrs[0].Size = ((arg1.Length + 1) * 2); descrs[0].Reserved = 0; @@ -924,7 +925,7 @@ protected unsafe void WriteEvent(int eventId, string? arg1, string? arg2, string fixed (char* string2Bytes = arg2) fixed (char* string3Bytes = arg3) { - EventSource.EventData* descrs = stackalloc EventSource.EventData[3]; + EventData* descrs = stackalloc EventData[3]; descrs[0].DataPointer = (IntPtr)string1Bytes; descrs[0].Size = ((arg1.Length + 1) * 2); descrs[0].Reserved = 0; @@ -949,7 +950,7 @@ protected unsafe void WriteEvent(int eventId, string? arg1, int arg2) arg1 ??= ""; fixed (char* string1Bytes = arg1) { - EventSource.EventData* descrs = stackalloc EventSource.EventData[2]; + EventData* descrs = stackalloc EventData[2]; descrs[0].DataPointer = (IntPtr)string1Bytes; descrs[0].Size = ((arg1.Length + 1) * 2); descrs[0].Reserved = 0; @@ -970,7 +971,7 @@ protected unsafe void WriteEvent(int eventId, string? arg1, int arg2, int arg3) arg1 ??= ""; fixed (char* string1Bytes = arg1) { - EventSource.EventData* descrs = stackalloc EventSource.EventData[3]; + EventData* descrs = stackalloc EventData[3]; descrs[0].DataPointer = (IntPtr)string1Bytes; descrs[0].Size = ((arg1.Length + 1) * 2); descrs[0].Reserved = 0; @@ -995,7 +996,7 @@ protected unsafe void WriteEvent(int eventId, string? arg1, long arg2) arg1 ??= ""; fixed (char* string1Bytes = arg1) { - EventSource.EventData* descrs = stackalloc EventSource.EventData[2]; + EventData* descrs = stackalloc EventData[2]; descrs[0].DataPointer = (IntPtr)string1Bytes; descrs[0].Size = ((arg1.Length + 1) * 2); descrs[0].Reserved = 0; @@ -1017,7 +1018,7 @@ protected unsafe void WriteEvent(int eventId, long arg1, string? arg2) arg2 ??= ""; fixed (char* string2Bytes = arg2) { - EventSource.EventData* descrs = stackalloc EventSource.EventData[2]; + EventData* descrs = stackalloc EventData[2]; descrs[0].DataPointer = (IntPtr)(&arg1); descrs[0].Size = 8; descrs[0].Reserved = 0; @@ -1039,7 +1040,7 @@ protected unsafe void WriteEvent(int eventId, int arg1, string? arg2) arg2 ??= ""; fixed (char* string2Bytes = arg2) { - EventSource.EventData* descrs = stackalloc EventSource.EventData[2]; + EventData* descrs = stackalloc EventData[2]; descrs[0].DataPointer = (IntPtr)(&arg1); descrs[0].Size = 4; descrs[0].Reserved = 0; @@ -1057,7 +1058,7 @@ protected unsafe void WriteEvent(int eventId, byte[]? arg1) { if (IsEnabled()) { - EventSource.EventData* descrs = stackalloc EventSource.EventData[2]; + EventData* descrs = stackalloc EventData[2]; if (arg1 == null || arg1.Length == 0) { int blobSize = 0; @@ -1092,7 +1093,7 @@ protected unsafe void WriteEvent(int eventId, long arg1, byte[]? arg2) { if (IsEnabled()) { - EventSource.EventData* descrs = stackalloc EventSource.EventData[3]; + EventData* descrs = stackalloc EventData[3]; descrs[0].DataPointer = (IntPtr)(&arg1); descrs[0].Size = 8; descrs[0].Reserved = 0; @@ -1216,7 +1217,7 @@ internal unsafe void SetMetadata(byte* pointer, int size, int reserved) "requires unreferenced code, but EnsureDescriptorsInitialized does not access this member and is safe to call.")] [RequiresUnreferencedCode(EventSourceRequiresUnreferenceMessage)] [CLSCompliant(false)] - protected unsafe void WriteEventCore(int eventId, int eventDataCount, EventSource.EventData* data) + protected unsafe void WriteEventCore(int eventId, int eventDataCount, EventData* data) { WriteEventWithRelatedActivityIdCore(eventId, null, eventDataCount, data); } @@ -1251,7 +1252,7 @@ protected unsafe void WriteEventCore(int eventId, int eventDataCount, EventSourc "requires unreferenced code, but EnsureDescriptorsInitialized does not access this member and is safe to call.")] [RequiresUnreferencedCode(EventSourceRequiresUnreferenceMessage)] [CLSCompliant(false)] - protected unsafe void WriteEventWithRelatedActivityIdCore(int eventId, Guid* relatedActivityId, int eventDataCount, EventSource.EventData* data) + protected unsafe void WriteEventWithRelatedActivityIdCore(int eventId, Guid* relatedActivityId, int eventDataCount, EventData* data) { if (IsEnabled()) { @@ -2173,6 +2174,8 @@ static TraceLoggingEventTypes GetTrimSafeTraceLoggingEventTypes() => #endif // FEATURE_MANAGED_ETW || FEATURE_PERFTRACING } + private static ReadOnlyCollection? s_errorPayloadNames; + /// /// Since this is a means of reporting errors (see ReportoutOfBandMessage) any failure encountered /// while writing the message to any one of the listeners will be silently ignored. @@ -2184,7 +2187,7 @@ private void WriteStringToAllListeners(string eventName, string msg) EventName = eventName, Message = msg, Payload = new ReadOnlyCollection(new object[] { msg }), - PayloadNames = new ReadOnlyCollection(new string[] { "message" }) + PayloadNames = s_errorPayloadNames ??= new ReadOnlyCollection(new string[] { "message" }) }; for (EventDispatcher? dispatcher = m_Dispatchers; dispatcher != null; dispatcher = dispatcher.m_Next) @@ -2273,7 +2276,8 @@ private bool IsEnabledCommon(bool enabled, EventLevel currentLevel, EventKeyword } return true; } - [System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)] + + [MethodImpl(MethodImplOptions.NoInlining)] private void ThrowEventSourceException(string? eventName, Exception? innerEx = null) { // If we fail during out of band logging we may end up trying @@ -3329,7 +3333,7 @@ private static bool AttributeTypeNamesMatch(Type attributeType, Type reflectedAt foreach (string error in manifest.Errors) { if (!firstError) - msg += System.Environment.NewLine; + msg += Environment.NewLine; firstError = false; msg += error; } @@ -3744,7 +3748,7 @@ internal void ReportOutOfBandMessage(string msg) } // send message to debugger - Debugger.Log(0, null, $"EventSource Error: {msg}{System.Environment.NewLine}"); + Debugger.Log(0, null, $"EventSource Error: {msg}{Environment.NewLine}"); // Send it to all listeners. WriteEventString(msg); @@ -4259,7 +4263,7 @@ private static void CallDisableEventsIfNecessary(EventDispatcher eventDispatcher /// private static void RemoveReferencesToListenerInEventSources(EventListener listenerToRemove) { - Debug.Assert(Monitor.IsEntered(EventListener.EventListenersLock)); + Debug.Assert(Monitor.IsEntered(EventListenersLock)); // Foreach existing EventSource in the appdomain Debug.Assert(s_EventSources != null); @@ -5709,7 +5713,7 @@ static FieldInfo[] GetEnumFields(Type localEnumType) var sortedStrings = new string[stringTab.Keys.Count]; stringTab.Keys.CopyTo(sortedStrings, 0); - Array.Sort(sortedStrings, StringComparer.Ordinal); + Array.Sort(sortedStrings, StringComparer.Ordinal); CultureInfo ci = CultureInfo.CurrentUICulture; sb.Append(" "); diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/FrameworkEventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/FrameworkEventSource.cs index 9e2766dc8c149a..f8ce8aebe672e8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/FrameworkEventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/FrameworkEventSource.cs @@ -45,7 +45,7 @@ private unsafe void WriteEvent(int eventId, long arg1, int arg2, string? arg3, b arg3 ??= ""; fixed (char* string3Bytes = arg3) { - EventSource.EventData* descrs = stackalloc EventSource.EventData[6]; + EventData* descrs = stackalloc EventData[6]; descrs[0].DataPointer = (IntPtr)(&arg1); descrs[0].Size = 8; descrs[0].Reserved = 0; @@ -80,7 +80,7 @@ private unsafe void WriteEvent(int eventId, long arg1, int arg2, string? arg3) arg3 ??= ""; fixed (char* string3Bytes = arg3) { - EventSource.EventData* descrs = stackalloc EventSource.EventData[3]; + EventData* descrs = stackalloc EventData[3]; descrs[0].DataPointer = (IntPtr)(&arg1); descrs[0].Size = 8; descrs[0].Reserved = 0; diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/IncrementingEventCounter.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/IncrementingEventCounter.cs index 3779b2639b8d6e..ff41451b0af0dc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/IncrementingEventCounter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/IncrementingEventCounter.cs @@ -14,7 +14,7 @@ namespace System.Diagnostics.Tracing /// #if !ES_BUILD_STANDALONE #if !FEATURE_WASM_PERFTRACING - [System.Runtime.Versioning.UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("browser")] #endif #endif public partial class IncrementingEventCounter : DiagnosticCounter diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/IncrementingPollingCounter.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/IncrementingPollingCounter.cs index 35256d88f97fb3..b0561a451cd567 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/IncrementingPollingCounter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/IncrementingPollingCounter.cs @@ -16,7 +16,7 @@ namespace System.Diagnostics.Tracing /// #if !ES_BUILD_STANDALONE #if !FEATURE_WASM_PERFTRACING - [System.Runtime.Versioning.UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("browser")] #endif #endif public partial class IncrementingPollingCounter : DiagnosticCounter diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/PollingCounter.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/PollingCounter.cs index c295c260379d8b..52196f8817fac3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/PollingCounter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/PollingCounter.cs @@ -15,7 +15,7 @@ namespace System.Diagnostics.Tracing /// #if !ES_BUILD_STANDALONE #if !FEATURE_WASM_PERFTRACING - [System.Runtime.Versioning.UnsupportedOSPlatform("browser")] + [UnsupportedOSPlatform("browser")] #endif #endif public partial class PollingCounter : DiagnosticCounter diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs index 2bed9b8b8679fa..d81a34095b9f50 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/RuntimeEventSource.cs @@ -60,7 +60,7 @@ public static void Initialize() { // initializing more than once may lead to missing events Debug.Assert(s_RuntimeEventSource == null); - if (EventSource.IsSupported) + if (IsSupported) s_RuntimeEventSource = new RuntimeEventSource(); } @@ -77,13 +77,13 @@ private enum EventId : int [Event((int)EventId.AppContextSwitch, Level = EventLevel.Informational, Keywords = Keywords.AppContext)] internal void LogAppContextSwitch(string switchName, int value) { - base.WriteEvent((int)EventId.AppContextSwitch, switchName, value); + WriteEvent((int)EventId.AppContextSwitch, switchName, value); } [Event((int)EventId.ProcessorCount, Level = EventLevel.Informational, Keywords = Keywords.ProcessorCount)] internal void ProcessorCount(int processorCount) { - base.WriteEvent((int)EventId.ProcessorCount, processorCount); + WriteEvent((int)EventId.ProcessorCount, processorCount); } protected override void OnEventCommand(EventCommandEventArgs command) @@ -120,11 +120,11 @@ protected override void OnEventCommand(EventCommandEventArgs command) _gen2SizeCounter ??= new PollingCounter("gen-2-size", this, () => GC.GetGenerationSize(2)) { DisplayName = "Gen 2 Size", DisplayUnits = "B" }; _lohSizeCounter ??= new PollingCounter("loh-size", this, () => GC.GetGenerationSize(3)) { DisplayName = "LOH Size", DisplayUnits = "B" }; _pohSizeCounter ??= new PollingCounter("poh-size", this, () => GC.GetGenerationSize(4)) { DisplayName = "POH (Pinned Object Heap) Size", DisplayUnits = "B" }; - _assemblyCounter ??= new PollingCounter("assembly-count", this, () => System.Reflection.Assembly.GetAssemblyCount()) { DisplayName = "Number of Assemblies Loaded" }; + _assemblyCounter ??= new PollingCounter("assembly-count", this, () => Reflection.Assembly.GetAssemblyCount()) { DisplayName = "Number of Assemblies Loaded" }; - _ilBytesJittedCounter ??= new PollingCounter("il-bytes-jitted", this, () => System.Runtime.JitInfo.GetCompiledILBytes()) { DisplayName = "IL Bytes Jitted", DisplayUnits = "B" }; - _methodsJittedCounter ??= new PollingCounter("methods-jitted-count", this, () => System.Runtime.JitInfo.GetCompiledMethodCount()) { DisplayName = "Number of Methods Jitted" }; - _jitTimeCounter ??= new IncrementingPollingCounter("time-in-jit", this, () => System.Runtime.JitInfo.GetCompilationTime().TotalMilliseconds) { DisplayName = "Time spent in JIT", DisplayUnits = "ms", DisplayRateTimeScale = new TimeSpan(0, 0, 1) }; + _ilBytesJittedCounter ??= new PollingCounter("il-bytes-jitted", this, () => Runtime.JitInfo.GetCompiledILBytes()) { DisplayName = "IL Bytes Jitted", DisplayUnits = "B" }; + _methodsJittedCounter ??= new PollingCounter("methods-jitted-count", this, () => Runtime.JitInfo.GetCompiledMethodCount()) { DisplayName = "Number of Methods Jitted" }; + _jitTimeCounter ??= new IncrementingPollingCounter("time-in-jit", this, () => Runtime.JitInfo.GetCompilationTime().TotalMilliseconds) { DisplayName = "Time spent in JIT", DisplayUnits = "ms", DisplayRateTimeScale = new TimeSpan(0, 0, 1) }; AppContext.LogSwitchValues(this); ProcessorCount(Environment.ProcessorCount); diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/EventPayload.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/EventPayload.cs index 93ecdb8ceb1f2d..a0ac46cc1815df 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/EventPayload.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/EventPayload.cs @@ -41,24 +41,24 @@ public object? this[string key] position++; } - throw new System.Collections.Generic.KeyNotFoundException(SR.Format(SR.Arg_KeyNotFoundWithKey, key)); + throw new KeyNotFoundException(SR.Format(SR.Arg_KeyNotFoundWithKey, key)); } - set => throw new System.NotSupportedException(); + set => throw new NotSupportedException(); } public void Add(string key, object? value) { - throw new System.NotSupportedException(); + throw new NotSupportedException(); } public void Add(KeyValuePair payloadEntry) { - throw new System.NotSupportedException(); + throw new NotSupportedException(); } public void Clear() { - throw new System.NotSupportedException(); + throw new NotSupportedException(); } public bool Contains(KeyValuePair entry) @@ -94,17 +94,17 @@ public bool ContainsKey(string key) public void CopyTo(KeyValuePair[] payloadEntries, int count) { - throw new System.NotSupportedException(); + throw new NotSupportedException(); } public bool Remove(string key) { - throw new System.NotSupportedException(); + throw new NotSupportedException(); } public bool Remove(KeyValuePair entry) { - throw new System.NotSupportedException(); + throw new NotSupportedException(); } public bool TryGetValue(string key, [MaybeNullWhen(false)] out object? value) diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/PropertyValue.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/PropertyValue.cs index cd6237c3fcc758..158db9c20fa310 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/PropertyValue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/PropertyValue.cs @@ -11,7 +11,7 @@ namespace System.Diagnostics.Tracing /// Holds property values of any type. For common value types, we have inline storage so that we don't need /// to box the values. For all other types, we store the value in a single object reference field. /// - /// To get the value of a property quickly, use a delegate produced by . + /// To get the value of a property quickly, use a delegate produced by . /// internal readonly unsafe struct PropertyValue { diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/SimpleEventTypes.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/SimpleEventTypes.cs index f6db3a6f4619eb..1e43118e6db6b7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/SimpleEventTypes.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/SimpleEventTypes.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.CodeAnalysis; using System.Threading; namespace System.Diagnostics.Tracing @@ -19,11 +20,11 @@ internal static class SimpleEventTypes public static TraceLoggingEventTypes Instance { - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource WriteEvent 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")] + [RequiresUnreferencedCode("EventSource WriteEvent 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")] get { return instance ??= InitInstance(); } } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource WriteEvent 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")] + [RequiresUnreferencedCode("EventSource WriteEvent 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 static TraceLoggingEventTypes InitInstance() { var info = TraceLoggingTypeInfo.GetInstance(typeof(T), null); diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs index 5e2482a2357edb..e31a51ad494abc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/SimpleTypeInfos.cs @@ -311,13 +311,13 @@ internal sealed class NullableTypeInfo : TraceLoggingTypeInfo { private readonly TraceLoggingTypeInfo valueInfo; - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource WriteEvent 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")] + [RequiresUnreferencedCode("EventSource WriteEvent 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")] public NullableTypeInfo(Type type, List recursionCheck) : base(type) { Type[] typeArgs = type.GenericTypeArguments; Debug.Assert(typeArgs.Length == 1); - this.valueInfo = TraceLoggingTypeInfo.GetInstance(typeArgs[0], recursionCheck); + this.valueInfo = GetInstance(typeArgs[0], recursionCheck); } public override void WriteMetadata( diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/Statics.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/Statics.cs index e1780509851900..ecd470dac69bb9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/Statics.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/Statics.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Runtime.CompilerServices; using System.Text; @@ -83,7 +84,7 @@ public static byte[] MetadataForString( int suffixSize, int additionalSize) { - Statics.CheckName(name); + CheckName(name); int metadataSize = Encoding.UTF8.GetByteCount(name) + 3 + prefixSize + suffixSize; var metadata = new byte[metadataSize]; ushort totalSize = checked((ushort)(metadataSize + additionalSize)); @@ -355,7 +356,7 @@ public static bool HasCustomAttribute( } public static Type? FindEnumerableElementType( - [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembers(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.Interfaces)] + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] Type type) { Type? elementType = null; @@ -389,7 +390,7 @@ public static bool IsGenericMatch(Type type, object? openType) return type.IsGenericType && type.GetGenericTypeDefinition() == (Type?)openType; } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource WriteEvent 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")] + [RequiresUnreferencedCode("EventSource WriteEvent 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")] public static TraceLoggingTypeInfo CreateDefaultTypeInfo( Type dataType, List recursionCheck) @@ -403,9 +404,9 @@ public static TraceLoggingTypeInfo CreateDefaultTypeInfo( recursionCheck.Add(dataType); - EventDataAttribute? eventAttrib = Statics.GetCustomAttribute(dataType); + EventDataAttribute? eventAttrib = GetCustomAttribute(dataType); if (eventAttrib != null || - Statics.GetCustomAttribute(dataType) != null || + GetCustomAttribute(dataType) != null || IsGenericMatch(dataType, typeof(KeyValuePair<,>))) { var analysis = new TypeAnalysis(dataType, eventAttrib, recursionCheck); diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventTypes.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventTypes.cs index b59bf884daa8a7..e870c2c377590c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventTypes.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingEventTypes.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace System.Diagnostics.Tracing { @@ -41,7 +42,7 @@ internal sealed class TraceLoggingEventTypes /// /// The types of the fields in the event. This value must not be null. /// - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource WriteEvent 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")] + [RequiresUnreferencedCode("EventSource WriteEvent 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")] internal TraceLoggingEventTypes( string name, EventTags tags, @@ -76,11 +77,11 @@ internal TraceLoggingEventTypes( { } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource WriteEvent 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")] + [RequiresUnreferencedCode("EventSource WriteEvent 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")] internal TraceLoggingEventTypes( string name, EventTags tags, - System.Reflection.ParameterInfo[] paramInfos) + Reflection.ParameterInfo[] paramInfos) { ArgumentNullException.ThrowIfNull(name); @@ -169,8 +170,8 @@ internal NameInfo GetNameInfo(string name, EventTags tags) => this.nameInfos.TryGet(new KeyValuePair(name, tags)) ?? this.nameInfos.GetOrAdd(new NameInfo(name, tags, this.typeMetadata.Length)); - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource WriteEvent 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 static TraceLoggingTypeInfo[] MakeArray(System.Reflection.ParameterInfo[] paramInfos) + [RequiresUnreferencedCode("EventSource WriteEvent 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 static TraceLoggingTypeInfo[] MakeArray(Reflection.ParameterInfo[] paramInfos) { ArgumentNullException.ThrowIfNull(paramInfos); @@ -184,7 +185,7 @@ private static TraceLoggingTypeInfo[] MakeArray(System.Reflection.ParameterInfo[ return result; } - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource WriteEvent 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")] + [RequiresUnreferencedCode("EventSource WriteEvent 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 static TraceLoggingTypeInfo[] MakeArray(Type[] types) { ArgumentNullException.ThrowIfNull(types); @@ -209,7 +210,7 @@ private static TraceLoggingTypeInfo[] MakeArray( #if FEATURE_PERFTRACING private static string[] MakeParamNameArray( - System.Reflection.ParameterInfo[] paramInfos) + Reflection.ParameterInfo[] paramInfos) { string[] paramNames = new string[paramInfos.Length]; for (int i = 0; i < paramNames.Length; i++) diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingTypeInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingTypeInfo.cs index e7eed6f6e9c560..8d584f5dc64d92 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingTypeInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TraceLoggingTypeInfo.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; namespace System.Diagnostics.Tracing { @@ -136,7 +137,7 @@ public abstract void WriteMetadata( [ThreadStatic] // per-thread cache to avoid synchronization private static Dictionary? threadCache; - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource WriteEvent 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")] + [RequiresUnreferencedCode("EventSource WriteEvent 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")] public static TraceLoggingTypeInfo GetInstance(Type type, List? recursionCheck) { Dictionary cache = threadCache ??= new Dictionary(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TypeAnalysis.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TypeAnalysis.cs index 31c2a53aff12ee..9325501afc8069 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TypeAnalysis.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Tracing/TraceLogging/TypeAnalysis.cs @@ -19,7 +19,7 @@ internal sealed class TypeAnalysis internal readonly EventOpcode opcode = (EventOpcode)(-1); internal readonly EventTags tags; - [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCode("EventSource WriteEvent 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")] + [RequiresUnreferencedCode("EventSource WriteEvent 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")] public TypeAnalysis( Type dataType, EventDataAttribute? eventAttrib, diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/UnreachableException.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/UnreachableException.cs index be8ff08940eebe..1b1a22b50995fb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/UnreachableException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/UnreachableException.cs @@ -9,7 +9,7 @@ namespace System.Diagnostics public sealed class UnreachableException : Exception { /// - /// Initializes a new instance of the class with the default error message. + /// Initializes a new instance of the class with the default error message. /// public UnreachableException() : base(SR.Arg_UnreachableException) @@ -17,7 +17,7 @@ public UnreachableException() } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class with a specified error message. /// /// The error message that explains the reason for the exception. @@ -27,7 +27,7 @@ public UnreachableException(string? message) } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class with a specified error message and a reference to the inner exception that is the cause of /// this exception. /// diff --git a/src/libraries/System.Private.CoreLib/src/System/DivideByZeroException.cs b/src/libraries/System.Private.CoreLib/src/System/DivideByZeroException.cs index 7db76dc9f2d350..8c58e5cf7281e3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DivideByZeroException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DivideByZeroException.cs @@ -11,12 +11,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class DivideByZeroException : ArithmeticException { public DivideByZeroException() diff --git a/src/libraries/System.Private.CoreLib/src/System/DllNotFoundException.cs b/src/libraries/System.Private.CoreLib/src/System/DllNotFoundException.cs index 3da70e3f7be0ae..6836322843b5f3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DllNotFoundException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DllNotFoundException.cs @@ -12,12 +12,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class DllNotFoundException : TypeLoadException { public DllNotFoundException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Double.cs b/src/libraries/System.Private.CoreLib/src/System/Double.cs index 523ad54c060472..aaa637ae02a6f3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Double.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Double.cs @@ -199,7 +199,7 @@ public static unsafe bool IsNegative(double d) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsNegativeInfinity(double d) { - return d == double.NegativeInfinity; + return d == NegativeInfinity; } /// Determines whether the specified value is normal. @@ -217,7 +217,7 @@ public static unsafe bool IsNormal(double d) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool IsPositiveInfinity(double d) { - return d == double.PositiveInfinity; + return d == PositiveInfinity; } /// Determines whether the specified value is subnormal. @@ -1167,21 +1167,21 @@ public static double MinMagnitudeNumber(double x, double y) [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out double result) { - return TryConvertFrom(value, out result); + return TryConvertFrom(value, out result); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromSaturating(TOther value, out double result) { - return TryConvertFrom(value, out result); + return TryConvertFrom(value, out result); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromTruncating(TOther value, out double result) { - return TryConvertFrom(value, out result); + return TryConvertFrom(value, out result); } private static bool TryConvertFrom(TOther value, out double result) @@ -1323,14 +1323,14 @@ static bool INumberBase.TryConvertToChecked(double value, [Maybe [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertToSaturating(double value, [MaybeNullWhen(false)] out TOther result) { - return TryConvertTo(value, out result); + return TryConvertTo(value, out result); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertToTruncating(double value, [MaybeNullWhen(false)] out TOther result) { - return TryConvertTo(value, out result); + return TryConvertTo(value, out result); } private static bool TryConvertTo(double value, [MaybeNullWhen(false)] out TOther result) diff --git a/src/libraries/System.Private.CoreLib/src/System/DuplicateWaitObjectException.cs b/src/libraries/System.Private.CoreLib/src/System/DuplicateWaitObjectException.cs index 24c86492ec822e..d7fc7c46be958a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/DuplicateWaitObjectException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/DuplicateWaitObjectException.cs @@ -11,6 +11,7 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System @@ -18,7 +19,7 @@ namespace System // The DuplicateWaitObjectException is thrown when an object // appears more than once in the list of objects to WaitAll or WaitAny. [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class DuplicateWaitObjectException : ArgumentException { // Creates a new DuplicateWaitObjectException with its message diff --git a/src/libraries/System.Private.CoreLib/src/System/EntryPointNotFoundException.cs b/src/libraries/System.Private.CoreLib/src/System/EntryPointNotFoundException.cs index d6677ed353edf7..5df0ea7885bf02 100644 --- a/src/libraries/System.Private.CoreLib/src/System/EntryPointNotFoundException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/EntryPointNotFoundException.cs @@ -11,12 +11,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class EntryPointNotFoundException : TypeLoadException { public EntryPointNotFoundException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.Windows.cs index 5344f92ac8e5d4..01339a82477d4e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Environment.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Environment.Windows.cs @@ -120,7 +120,7 @@ private static unsafe bool IsPrivilegedProcessCore() Interop.Kernel32.GetComputerName() ?? throw new InvalidOperationException(SR.InvalidOperation_ComputerName); - [MethodImplAttribute(MethodImplOptions.NoInlining)] // Avoid inlining PInvoke frame into the hot path + [MethodImpl(MethodImplOptions.NoInlining)] // Avoid inlining PInvoke frame into the hot path private static int GetProcessId() => unchecked((int)Interop.Kernel32.GetCurrentProcessId()); private static string? GetProcessPath() diff --git a/src/libraries/System.Private.CoreLib/src/System/Environment.cs b/src/libraries/System.Private.CoreLib/src/System/Environment.cs index da368b943ff7cf..53028ec74d0219 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Environment.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Environment.cs @@ -222,7 +222,7 @@ public static Version Version public static string StackTrace { [MethodImpl(MethodImplOptions.NoInlining)] // Prevent inlining from affecting where the stacktrace starts - get => new StackTrace(true).ToString(System.Diagnostics.StackTrace.TraceFormat.Normal); + get => new StackTrace(true).ToString(Diagnostics.StackTrace.TraceFormat.Normal); } private static volatile int s_systemPageSize; diff --git a/src/libraries/System.Private.CoreLib/src/System/EventArgs.cs b/src/libraries/System.Private.CoreLib/src/System/EventArgs.cs index 38b95c80f6d09b..9141ca7f6fd1f1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/EventArgs.cs +++ b/src/libraries/System.Private.CoreLib/src/System/EventArgs.cs @@ -1,11 +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.Runtime.CompilerServices; + namespace System { // The base class for all event classes. [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class EventArgs { public static readonly EventArgs Empty = new EventArgs(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Exception.cs b/src/libraries/System.Private.CoreLib/src/System/Exception.cs index f7d5139e98a939..2e59e4b792ad31 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Exception.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Exception.cs @@ -5,13 +5,14 @@ using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Text; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public partial class Exception : ISerializable { private protected const string InnerExceptionPrefix = " ---> "; @@ -228,7 +229,7 @@ public virtual string? StackTrace private string GetStackTrace() { // Do not include a trailing newline for backwards compatibility - return new StackTrace(this, fNeedFileInfo: true).ToString(System.Diagnostics.StackTrace.TraceFormat.Normal); + return new StackTrace(this, fNeedFileInfo: true).ToString(Diagnostics.StackTrace.TraceFormat.Normal); } [StackTraceHidden] @@ -243,7 +244,7 @@ internal void SetCurrentStackTrace() // remoting of exceptions cross app-domain boundaries, and is thus concatenated into Exception.StackTrace // when it's retrieved. var sb = new StringBuilder(256); - new StackTrace(fNeedFileInfo: true).ToString(System.Diagnostics.StackTrace.TraceFormat.TrailingNewLine, sb); + new StackTrace(fNeedFileInfo: true).ToString(Diagnostics.StackTrace.TraceFormat.TrailingNewLine, sb); sb.AppendLine(SR.Exception_EndStackTraceFromPreviousThrow); _remoteStackTraceString = sb.ToString(); } diff --git a/src/libraries/System.Private.CoreLib/src/System/ExecutionEngineException.cs b/src/libraries/System.Private.CoreLib/src/System/ExecutionEngineException.cs index 0c5dc2d66481a4..139d391ce1d642 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ExecutionEngineException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ExecutionEngineException.cs @@ -14,13 +14,14 @@ ** =============================================================================*/ +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Obsolete("ExecutionEngineException previously indicated an unspecified fatal error in the runtime. The runtime no longer raises this exception so this type is obsolete.")] [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class ExecutionEngineException : SystemException { public ExecutionEngineException() diff --git a/src/libraries/System.Private.CoreLib/src/System/FieldAccessException.cs b/src/libraries/System.Private.CoreLib/src/System/FieldAccessException.cs index 2fbdd9d53e0336..ae929df93eeb71 100644 --- a/src/libraries/System.Private.CoreLib/src/System/FieldAccessException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/FieldAccessException.cs @@ -9,12 +9,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class FieldAccessException : MemberAccessException { public FieldAccessException() diff --git a/src/libraries/System.Private.CoreLib/src/System/FormatException.cs b/src/libraries/System.Private.CoreLib/src/System/FormatException.cs index 2eee0bca9ce988..4cca4845f13853 100644 --- a/src/libraries/System.Private.CoreLib/src/System/FormatException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/FormatException.cs @@ -11,12 +11,13 @@ ===========================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class FormatException : SystemException { public FormatException() diff --git a/src/libraries/System.Private.CoreLib/src/System/GCMemoryInfo.cs b/src/libraries/System.Private.CoreLib/src/System/GCMemoryInfo.cs index 6f3c0e034d548f..59cce34d7d4038 100644 --- a/src/libraries/System.Private.CoreLib/src/System/GCMemoryInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/GCMemoryInfo.cs @@ -77,12 +77,12 @@ internal sealed class GCMemoryInfoData private GCGenerationInfo _generationInfo3; private GCGenerationInfo _generationInfo4; - internal ReadOnlySpan GenerationInfoAsSpan => MemoryMarshal.CreateReadOnlySpan(ref _generationInfo0, 5); + internal ReadOnlySpan GenerationInfoAsSpan => MemoryMarshal.CreateReadOnlySpan(ref _generationInfo0, 5); private TimeSpan _pauseDuration0; private TimeSpan _pauseDuration1; - internal ReadOnlySpan PauseDurationsAsSpan => MemoryMarshal.CreateReadOnlySpan(ref _pauseDuration0, 2); + internal ReadOnlySpan PauseDurationsAsSpan => MemoryMarshal.CreateReadOnlySpan(ref _pauseDuration0, 2); } /// Provides a set of APIs that can be used to retrieve garbage collection information. diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendarData.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendarData.cs index fa1662b1f5979c..d96ede7b7244f6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendarData.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendarData.cs @@ -322,7 +322,7 @@ internal static int GetCalendarCurrentEra(Calendar calendar) { if (GlobalizationMode.Invariant) { - return CalendarData.Invariant.iCurrentEra; + return Invariant.iCurrentEra; } // diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendricalCalculationsHelper.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendricalCalculationsHelper.cs index fc7203aadcdac9..e99e9fab1426b3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendricalCalculationsHelper.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CalendricalCalculationsHelper.cs @@ -59,12 +59,12 @@ private static double Obliquity(double julianCenturies) internal static long GetNumberOfDays(DateTime date) { - return date.Ticks / GregorianCalendar.TicksPerDay; + return date.Ticks / Calendar.TicksPerDay; } private static int GetGregorianYear(double numberOfDays) { - return new DateTime(Math.Min((long)(Math.Floor(numberOfDays) * GregorianCalendar.TicksPerDay), DateTime.MaxValue.Ticks)).Year; + return new DateTime(Math.Min((long)(Math.Floor(numberOfDays) * Calendar.TicksPerDay), DateTime.MaxValue.Ticks)).Year; } private enum CorrectionAlgorithm 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 aa8cb4391d480e..2eeb65d50321c5 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 @@ -12,6 +12,88 @@ internal sealed partial class CultureData // ICU constants private const int ICU_ULOC_KEYWORD_AND_VALUES_CAPACITY = 100; // max size of keyword or value private const int ICU_ULOC_FULLNAME_CAPACITY = 157; // max size of locale name + private const int WINDOWS_MAX_COLLATION_NAME_LENGTH = 8; // max collation name length in the culture name + + /// + /// Process the locale name that ICU returns and convert it to the format that .NET expects. + /// + /// The locale name that ICU returns. + /// The extension part in the original culture name. + /// The index of the collation in the name. + /// + /// BCP 47 specifications allow for extensions in the locale name, following the format language-script-region-extensions-collation. However, + /// not all extensions supported by ICU are supported in .NET. In the locale name, extensions are separated from the rest of the name using '-u-' or '-t-'. + /// In .NET, only the collation extension is supported. If the name includes a collation extension, it will be prefixed with '-u-co-'. + /// For example, en-US-u-co-search would be converted to the ICU name en_US@collation=search, which would then be translated to the .NET name en-US_search. + /// All extensions in the ICU names start with @. When normalizing the name to the .NET format, we retain the extensions in the name to ensure differentiation + /// between names with extensions and those without. For example, we may have a name like en-US and en-US-u-xx. Although .NET doesn't support the extension xx, + /// we still include it in the name to distinguish it from the name without the extension. + /// + private static string NormalizeCultureName(string name, ReadOnlySpan extension, out int collationStart) + { + Debug.Assert(name is not null); + Debug.Assert(name.Length <= ICU_ULOC_FULLNAME_CAPACITY); + + collationStart = -1; + bool changed = false; + Span buffer = stackalloc char[ICU_ULOC_FULLNAME_CAPACITY]; + int bufferIndex = 0; + + for (int i = 0; i < name.Length && bufferIndex < ICU_ULOC_FULLNAME_CAPACITY; i++) + { + char c = name[i]; + if (c == '-' && i < name.Length - 1 && name[i + 1] == '-') + { + // ICU changes names like `qps_plocm` (one underscore) to `qps__plocm` (two underscores) + // The reason this occurs is because, while ICU canonicalizing, ulocimp_getCountry returns an empty string since the country code value is > 3 (rightly so). + // But append an extra '_' thinking that country code was in-fact appended (for the empty string value as well). + // Before processing, the name qps__plocm will be converted to its .NET name equivalent, which is qps--plocm. + changed = true; + buffer[bufferIndex++] = '-'; + i++; + } + else if (c == '@') + { + changed = true; + + if (!extension.IsEmpty && extension.TryCopyTo(buffer.Slice(bufferIndex))) + { + bufferIndex += extension.Length; + } + + int collationIndex = name.IndexOf("collation=", i + 1, StringComparison.Ordinal); + if (collationIndex > 0) + { + collationIndex += "collation=".Length; + + // format of the locale properties is @key=value;collation=collationName;key=value;key=value + int endOfCollation = name.IndexOf(';', collationIndex); + if (endOfCollation < 0) + { + endOfCollation = name.Length; + } + + int length = Math.Min(WINDOWS_MAX_COLLATION_NAME_LENGTH, endOfCollation - collationIndex); // Windows doesn't allow collation names longer than 8 characters + if (buffer.Length - bufferIndex >= length + 1) + { + collationStart = bufferIndex; + buffer[bufferIndex++] = '_'; + name.AsSpan(collationIndex, length).CopyTo(buffer.Slice(bufferIndex)); + bufferIndex += length; + } + } + + // done getting all parts can be supported in the .NET culture names. + break; + } + else + { + buffer[bufferIndex++] = name[i]; + } + } + + return changed ? new string(buffer.Slice(0, bufferIndex)) : name; + } /// /// This method uses the sRealName field (which is initialized by the constructor before this is called) to @@ -26,16 +108,15 @@ private bool InitIcuCultureDataCore() string realNameBuffer = _sRealName; // Basic validation - if (!IsValidCultureName(realNameBuffer, out var index)) + if (!IsValidCultureName(realNameBuffer, out var index, out int indexOfExtensions)) { return false; } // Replace _ (alternate sort) with @collation= for ICU - ReadOnlySpan alternateSortName = default; if (index > 0) { - alternateSortName = realNameBuffer.AsSpan(index + 1); + ReadOnlySpan alternateSortName = realNameBuffer.AsSpan(index + 1); realNameBuffer = string.Concat(realNameBuffer.AsSpan(0, index), ICU_COLLATION_KEYWORD, alternateSortName); } @@ -45,22 +126,9 @@ private bool InitIcuCultureDataCore() return false; // fail } - // Replace the ICU collation keyword with an _ Debug.Assert(_sWindowsName != null); - index = _sWindowsName.IndexOf(ICU_COLLATION_KEYWORD, StringComparison.Ordinal); - if (index >= 0) - { - // Use original culture name if alternateSortName is not set, which is possible even if the normalized - // culture name has "@collation=". - // "zh-TW-u-co-zhuyin" is a good example. The term "u-co-" means the following part will be the sort name - // and it will be treated in ICU as "zh-TW@collation=zhuyin". - _sName = alternateSortName.Length == 0 ? realNameBuffer : string.Concat(_sWindowsName.AsSpan(0, index), "_", alternateSortName); - } - else - { - _sName = _sWindowsName; - } - _sRealName = _sName; + + _sRealName = NormalizeCultureName(_sWindowsName, indexOfExtensions > 0 ? _sRealName.AsSpan(indexOfExtensions) : ReadOnlySpan.Empty, out int collationStart); _iLanguage = LCID; if (_iLanguage == 0) @@ -69,11 +137,15 @@ private bool InitIcuCultureDataCore() } _bNeutral = TwoLetterISOCountryName.Length == 0; _sSpecificCulture = _bNeutral ? IcuLocaleData.GetSpecificCultureName(_sRealName) : _sRealName; - // Remove the sort from sName unless custom culture - if (index > 0 && !_bNeutral && !IsCustomCultureId(_iLanguage)) + + if (_bNeutral && collationStart > 0) { - _sName = _sWindowsName.Substring(0, index); + return false; // neutral cultures cannot have collation } + + // Remove the sort from sName unless custom culture + _sName = collationStart < 0 ? _sRealName : _sRealName.Substring(0, collationStart); + return true; } @@ -289,7 +361,7 @@ private static int IcuGetGeoId(string cultureName) { Debug.Assert(!GlobalizationMode.UseNls); int geoId = IcuLocaleData.GetLocaleDataNumericPart(cultureName, IcuLocaleDataParts.GeoId); - return geoId == -1 ? CultureData.Invariant.GeoId : geoId; + return geoId == -1 ? Invariant.GeoId : geoId; } private const uint DigitSubstitutionMask = 0x0000FFFF; @@ -367,7 +439,7 @@ private static CultureInfo[] IcuEnumCultures(CultureTypes types) } bool enumNeutrals = (types & CultureTypes.NeutralCultures) != 0; - bool enumSpecificss = (types & CultureTypes.SpecificCultures) != 0; + bool enumSpecifics = (types & CultureTypes.SpecificCultures) != 0; List list = new List(); if (enumNeutrals) @@ -382,7 +454,7 @@ private static CultureInfo[] IcuEnumCultures(CultureTypes types) if (index + length <= bufferLength) { CultureInfo ci = CultureInfo.GetCultureInfo(new string(chars, index, length)); - if ((enumNeutrals && ci.IsNeutralCulture) || (enumSpecificss && !ci.IsNeutralCulture)) + if ((enumNeutrals && ci.IsNeutralCulture) || (enumSpecifics && !ci.IsNeutralCulture)) { list.Add(ci); } @@ -416,10 +488,14 @@ private static string IcuGetConsoleFallbackName(string cultureName) /// * Disallow input that starts or ends with '-' or '_'. /// * Disallow input that has any combination of consecutive '-' or '_'. /// * Disallow input that has multiple '_'. + /// + /// The IsValidCultureName method also identifies the presence of any extensions in the name (such as -u- or -t-) and returns the index of the extension. + /// This is necessary because we need to append the extensions to the name when normalizing it to the .NET format. /// - private static bool IsValidCultureName(string subject, out int indexOfUnderscore) + private static bool IsValidCultureName(string subject, out int indexOfUnderscore, out int indexOfExtensions) { indexOfUnderscore = -1; + indexOfExtensions = -1; if (subject.Length == 0) return true; // Invariant Culture if (subject.Length == 1 || subject.Length > LocaleNameMaxLength) return false; @@ -444,6 +520,16 @@ private static bool IsValidCultureName(string subject, out int indexOfUnderscore seenUnderscore = true; indexOfUnderscore = i; } + else + { + if (indexOfExtensions < 0 && i < subject.Length - 2 && (subject[i + 1] is 'u' or 't') && subject[i + 2] == '-') // we have -u- or -t- which is an extension + { + if (subject[i + 1] == 't' || i >= subject.Length - 6 || subject[i + 3] != 'c' || subject[i + 4] != 'o' || subject[i + 5] != '-' ) // not -u-co- collation extension + { + indexOfExtensions = i; + } + } + } } else { diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Nls.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Nls.cs index a32baa99ecbe14..69b75181505508 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Nls.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.Nls.cs @@ -90,7 +90,7 @@ private int[] NlsGetLocaleInfo(LocaleGroupingData type) internal static bool NlsIsEnsurePredefinedLocaleName(string name) { Debug.Assert(GlobalizationMode.UseNls); - return CultureData.GetLocaleInfoExInt(name, Interop.Kernel32.LOCALE_ICONSTRUCTEDLOCALE) != 1; + return GetLocaleInfoExInt(name, Interop.Kernel32.LOCALE_ICONSTRUCTEDLOCALE) != 1; } private string? NlsGetTimeFormatString() 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 12ea4ded8beedd..69c8ec34aa7156 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureData.cs @@ -424,7 +424,7 @@ internal sealed partial class CultureData // First do a shortcut for Invariant if (string.IsNullOrEmpty(cultureName)) { - return CultureData.Invariant; + return Invariant; } // First check if GetCultureData() can find it (ie: its a real culture) @@ -672,7 +672,7 @@ private static CultureData CreateCultureWithInvariantData() // First do a shortcut for Invariant if (string.IsNullOrEmpty(cultureName)) { - return CultureData.Invariant; + return Invariant; } if (GlobalizationMode.PredefinedCulturesOnly) @@ -804,7 +804,7 @@ private static string NormalizeCultureName(string name, out bool isNeutralName) // Always map the "C" locale to Invariant to avoid mapping it to en_US_POSIX on Linux because POSIX // locale collation doesn't support case insensitive comparisons. // We do the same mapping on Windows for the sake of consistency. - return CultureData.Invariant; + return Invariant; } CultureData culture = new CultureData(); @@ -868,6 +868,16 @@ internal static CultureData GetCultureData(int culture, bool bUseUserOverride) if (GlobalizationMode.Invariant) { + if (!GlobalizationMode.PredefinedCulturesOnly) + { + if (culture is < 1 or > 0xf_ffff) + { + throw new CultureNotFoundException(nameof(culture), culture, SR.Argument_CultureNotSupported); + } + + return Invariant; + } + // LCID is not supported in the InvariantMode throw new CultureNotFoundException(nameof(culture), culture, SR.Argument_CultureNotSupportedInInvariantMode); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.Windows.cs index e2ab1851141c7b..6773c723ed65db 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.Windows.cs @@ -8,19 +8,19 @@ public partial class CultureInfo : IFormatProvider internal static CultureInfo GetUserDefaultCulture() { if (GlobalizationMode.Invariant) - return CultureInfo.InvariantCulture; + return InvariantCulture; string? strDefault = UserDefaultLocaleName; return strDefault != null ? GetCultureByName(strDefault) : - CultureInfo.InvariantCulture; + InvariantCulture; } private static unsafe CultureInfo GetUserDefaultUICulture() { if (GlobalizationMode.Invariant) - return CultureInfo.InvariantCulture; + return InvariantCulture; const uint MUI_LANGUAGE_NAME = 0x8; // Use ISO language (culture) name convention uint langCount = 0; @@ -45,7 +45,7 @@ private static unsafe CultureInfo GetUserDefaultUICulture() private static string? GetUserDefaultLocaleName() => GlobalizationMode.Invariant ? - CultureInfo.InvariantCulture.Name : + InvariantCulture.Name : CultureData.GetLocaleInfoEx(Interop.Kernel32.LOCALE_NAME_USER_DEFAULT, Interop.Kernel32.LOCALE_SNAME) ?? CultureData.GetLocaleInfoEx(Interop.Kernel32.LOCALE_NAME_SYSTEM_DEFAULT, Interop.Kernel32.LOCALE_SNAME); } 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 d5c1f218c81619..31b17f3c4f5e3b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureInfo.cs @@ -405,7 +405,7 @@ public static CultureInfo CurrentUICulture { ArgumentNullException.ThrowIfNull(value); - CultureInfo.VerifyCultureName(value, true); + VerifyCultureName(value, true); if (s_asyncLocalCurrentUICulture == null) { @@ -443,7 +443,7 @@ public static CultureInfo? DefaultThreadCurrentUICulture if (value != null) { - CultureInfo.VerifyCultureName(value, true); + VerifyCultureName(value, true); } s_DefaultThreadCurrentUICulture = value; @@ -647,7 +647,7 @@ public virtual TextInfo TextInfo public override bool Equals([NotNullWhen(true)] object? value) { - if (object.ReferenceEquals(this, value)) + if (ReferenceEquals(this, value)) { return true; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureNotFoundException.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureNotFoundException.cs index 41f714b2cd1f96..49efb6232591e1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureNotFoundException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/CultureNotFoundException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Globalization { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class CultureNotFoundException : ArgumentException { private readonly string? _invalidCultureName; // unrecognized culture name 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 e0e2e7b5ffac9c..1ac08424bff49b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormatInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/DateTimeFormatInfo.cs @@ -297,7 +297,7 @@ public static DateTimeFormatInfo CurrentInfo { get { - System.Globalization.CultureInfo culture = System.Globalization.CultureInfo.CurrentCulture; + CultureInfo culture = CultureInfo.CurrentCulture; if (!culture._isInherited) { DateTimeFormatInfo? info = culture._dateTimeInfo; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/EastAsianLunisolarCalendar.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/EastAsianLunisolarCalendar.cs index f012ae3b0adf8e..3057bd0c08f7dc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/EastAsianLunisolarCalendar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/EastAsianLunisolarCalendar.cs @@ -82,7 +82,7 @@ internal int MinEraCalendarYear(int era) return MinCalendarYear; } - if (era == Calendar.CurrentEra) + if (era == CurrentEra) { era = CurrentEraValue; } @@ -112,7 +112,7 @@ internal int MaxEraCalendarYear(int era) return MaxCalendarYear; } - if (era == Calendar.CurrentEra) + if (era == CurrentEra) { era = CurrentEraValue; } @@ -152,7 +152,7 @@ internal void CheckTicksRange(long ticks) internal void CheckEraRange(int era) { - if (era == Calendar.CurrentEra) + if (era == CurrentEra) { era = CurrentEraValue; } 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 33c61798f8a2c4..520c5ef2c5d671 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/GregorianCalendar.cs @@ -165,7 +165,7 @@ public override DateTime AddMonths(DateTime time, int months) d = days; } long ticks = DateToTicks(y, m, d) + time.Ticks % TicksPerDay; - Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime); + CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime); return new DateTime(ticks); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/HebrewCalendar.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/HebrewCalendar.cs index 7a418cf21eadf0..0d7d74074d4762 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/HebrewCalendar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/HebrewCalendar.cs @@ -583,7 +583,7 @@ public override DateTime AddYears(DateTime time, int years) int d = GetDatePart(time.Ticks, DatePartDay); y += years; - CheckHebrewYearValue(y, Calendar.CurrentEra, nameof(years)); + CheckHebrewYearValue(y, CurrentEra, nameof(years)); int months = GetMonthsInYear(y, CurrentEra); if (m > months) @@ -598,7 +598,7 @@ public override DateTime AddYears(DateTime time, int years) } long ticks = ToDateTime(y, m, d, 0, 0, 0, 0).Ticks + (time.Ticks % TicksPerDay); - Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime); + CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime); return new DateTime(ticks); } @@ -711,7 +711,7 @@ public override bool IsLeapDay(int year, int month, int day, int era) CheckHebrewDayValue(year, month, day, era); return true; } - else if (IsLeapYear(year, Calendar.CurrentEra)) + else if (IsLeapYear(year, CurrentEra)) { // There is an additional day in the 6th month in the leap year (the extra day is the 30th day in the 6th month), // so we should return true for 6/30 if that's in a leap year. diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/HijriCalendar.Win32.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/HijriCalendar.Win32.cs index bee73ccb1bdc0d..7d01915375a643 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/HijriCalendar.Win32.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/HijriCalendar.Win32.cs @@ -57,22 +57,19 @@ private static int GetAdvanceHijriDate() if (string.Compare(str, 0, HijriAdvanceRegKeyEntry, 0, HijriAdvanceRegKeyEntry.Length, StringComparison.OrdinalIgnoreCase) == 0) { if (str!.Length == HijriAdvanceRegKeyEntry.Length) + { hijriAdvance = -1; + } else { - try + if (int.TryParse(str.AsSpan(HijriAdvanceRegKeyEntry.Length), CultureInfo.InvariantCulture, out int advance) && + (advance >= MinAdvancedHijri) && + (advance <= MaxAdvancedHijri)) { - int advance = int.Parse(str.AsSpan(HijriAdvanceRegKeyEntry.Length), provider: CultureInfo.InvariantCulture); - if ((advance >= MinAdvancedHijri) && (advance <= MaxAdvancedHijri)) - { - hijriAdvance = advance; - } + hijriAdvance = advance; } - // If we got garbage from registry just ignore it. + // If parsing fails due to garbage from registry just ignore it. // hijriAdvance = 0 because of declaraction assignment up above. - catch (ArgumentException) { } - catch (FormatException) { } - catch (OverflowException) { } } } return hijriAdvance; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/HijriCalendar.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/HijriCalendar.cs index 9bededeb7b3b01..6fcf8ec34e639b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/HijriCalendar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/HijriCalendar.cs @@ -198,7 +198,7 @@ internal virtual int GetDatePart(long ticks, int part) // Get the absolute date. The absolute date is the number of days from January 1st, 1 A.D. // 1/1/0001 is absolute date 1. - long numDays = ticks / GregorianCalendar.TicksPerDay + 1; + long numDays = ticks / TicksPerDay + 1; // See how much we need to backup or advance numDays += HijriAdjustment; @@ -297,7 +297,7 @@ public override DateTime AddMonths(DateTime time, int months) } long ticks = GetAbsoluteDateHijri(y, m, d) * TicksPerDay + (time.Ticks % TicksPerDay); - Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime); + CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime); return new DateTime(ticks); } @@ -413,7 +413,7 @@ public override DateTime ToDateTime(int year, int month, int day, int hour, int throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay); } - return new DateTime(lDate * GregorianCalendar.TicksPerDay + TimeToTicks(hour, minute, second, millisecond)); + return new DateTime(lDate * TicksPerDay + TimeToTicks(hour, minute, second, millisecond)); } private const int DefaultTwoDigitYearMax = 1451; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/InvariantModeCasing.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/InvariantModeCasing.cs index 45126b37c63b2c..6e85fb44d1ab53 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/InvariantModeCasing.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/InvariantModeCasing.cs @@ -57,7 +57,7 @@ internal static string ToLower(string s) var destination = new Span(ref result.GetRawStringData(), result.Length); ReadOnlySpan src = s; src.Slice(0, i).CopyTo(destination); - InvariantModeCasing.ToLower(src.Slice(i), destination.Slice(i)); + ToLower(src.Slice(i), destination.Slice(i)); return result; } @@ -103,7 +103,7 @@ internal static string ToUpper(string s) var destination = new Span(ref result.GetRawStringData(), result.Length); ReadOnlySpan src = s; src.Slice(0, i).CopyTo(destination); - InvariantModeCasing.ToUpper(src.Slice(i), destination.Slice(i)); + ToUpper(src.Slice(i), destination.Slice(i)); return result; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/JapaneseCalendar.Nls.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/JapaneseCalendar.Nls.cs index 1ae65aa57432db..dbe16fd517e231 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/JapaneseCalendar.Nls.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/JapaneseCalendar.Nls.cs @@ -67,17 +67,17 @@ public partial class JapaneseCalendar : Calendar } } } - catch (System.Security.SecurityException) + catch (Security.SecurityException) { // If we weren't allowed to read, then just ignore the error return null; } - catch (System.IO.IOException) + catch (IO.IOException) { // If key is being deleted just ignore the error return null; } - catch (System.UnauthorizedAccessException) + catch (UnauthorizedAccessException) { // Registry access rights permissions, just ignore the error return null; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/JulianCalendar.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/JulianCalendar.cs index 0db8614f24858d..8a86fc14e1c7e2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/JulianCalendar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/JulianCalendar.cs @@ -210,7 +210,7 @@ public override DateTime AddMonths(DateTime time, int months) } long ticks = DateToTicks(y, m, d) + time.Ticks % TicksPerDay; - Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime); + CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime); return new DateTime(ticks); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/Normalization.WebAssembly.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/Normalization.WebAssembly.cs deleted file mode 100644 index b930f6812904af..00000000000000 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/Normalization.WebAssembly.cs +++ /dev/null @@ -1,88 +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.Diagnostics; -using System.Runtime.InteropServices; -using System.Text; - -namespace System.Globalization -{ - internal static partial class Normalization - { - private static unsafe bool JsIsNormalized(string strInput, NormalizationForm normalizationForm) - { - Debug.Assert(!GlobalizationMode.Invariant); - Debug.Assert(!GlobalizationMode.UseNls); - - ValidateArguments(strInput, normalizationForm); - - int ret = Interop.JsGlobalization.IsNormalized(normalizationForm, strInput, out int exception, out object ex_result); - if (exception != 0) - throw new Exception((string)ex_result); - - return ret == 1; - } - - private static unsafe string JsNormalize(string strInput, NormalizationForm normalizationForm) - { - Debug.Assert(!GlobalizationMode.Invariant); - Debug.Assert(!GlobalizationMode.UseNls); - - ValidateArguments(strInput, normalizationForm); - - char[]? toReturn = null; - try - { - const int StackallocThreshold = 512; - - Span buffer = strInput.Length <= StackallocThreshold - ? stackalloc char[StackallocThreshold] - : (toReturn = ArrayPool.Shared.Rent(strInput.Length)); - - for (int attempt = 0; attempt < 2; attempt++) - { - int realLen; - fixed (char* pDest = &MemoryMarshal.GetReference(buffer)) - { - realLen = Interop.JsGlobalization.NormalizeString(normalizationForm, strInput, pDest, buffer.Length, out int exception, out object ex_result); - if (exception != 0) - throw new Exception((string)ex_result); - } - - if (realLen <= buffer.Length) - { - ReadOnlySpan result = buffer.Slice(0, realLen); - return result.SequenceEqual(strInput) - ? strInput - : new string(result); - } - - Debug.Assert(realLen > StackallocThreshold); - - if (attempt == 0) - { - if (toReturn != null) - { - // Clear toReturn first to ensure we don't return the same buffer twice - char[] temp = toReturn; - toReturn = null; - ArrayPool.Shared.Return(temp); - } - - buffer = toReturn = ArrayPool.Shared.Rent(realLen); - } - } - - throw new ArgumentException(SR.Argument_InvalidCharSequenceNoIndex, nameof(strInput)); - } - finally - { - if (toReturn != null) - { - ArrayPool.Shared.Return(toReturn); - } - } - } - } -} diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/Normalization.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/Normalization.cs index 2bc6107b5dad6c..d120302a8aa8e7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/Normalization.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/Normalization.cs @@ -19,10 +19,6 @@ internal static bool IsNormalized(string strInput, NormalizationForm normalizati return GlobalizationMode.UseNls ? NlsIsNormalized(strInput, normalizationForm) : -#if TARGET_BROWSER - GlobalizationMode.Hybrid ? - JsIsNormalized(strInput, normalizationForm) : -#endif IcuIsNormalized(strInput, normalizationForm); } @@ -37,10 +33,6 @@ internal static string Normalize(string strInput, NormalizationForm normalizatio return GlobalizationMode.UseNls ? NlsNormalize(strInput, normalizationForm) : -#if TARGET_BROWSER - GlobalizationMode.Hybrid ? - JsNormalize(strInput, normalizationForm) : -#endif IcuNormalize(strInput, normalizationForm); } } 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 ac22a353040c1b..9f4c2f7eb1c19d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs @@ -400,7 +400,7 @@ public static NumberFormatInfo CurrentInfo { get { - System.Globalization.CultureInfo culture = CultureInfo.CurrentCulture; + CultureInfo culture = CultureInfo.CurrentCulture; if (!culture._isInherited) { NumberFormatInfo? info = culture._numInfo; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs index a3bdd382defee3..8091c88d128c8d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/OrdinalCasing.Icu.cs @@ -217,8 +217,8 @@ internal static int CompareStringIgnoreCase(ref char strA, int lengthA, ref char continue; } - char aUpper = OrdinalCasing.ToUpper(a); - char bUpper = OrdinalCasing.ToUpper(b); + char aUpper = ToUpper(a); + char bUpper = ToUpper(b); if (aUpper == bUpper) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/PersianCalendar.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/PersianCalendar.cs index d4a93276b5159a..d6d4cb833b7b8a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/PersianCalendar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/PersianCalendar.cs @@ -21,7 +21,7 @@ public class PersianCalendar : Calendar { public static readonly int PersianEra = 1; - private static readonly long s_persianEpoch = new DateTime(622, 3, 22).Ticks / GregorianCalendar.TicksPerDay; + private static readonly long s_persianEpoch = new DateTime(622, 3, 22).Ticks / TicksPerDay; private const int ApproximateHalfYear = 180; private const int DatePartYear = 0; @@ -147,7 +147,7 @@ internal int GetDatePart(long ticks, int part) // Get the absolute date. The absolute date is the number of days from January 1st, 1 A.D. // 1/1/0001 is absolute date 1. - long numDays = ticks / GregorianCalendar.TicksPerDay + 1; + long numDays = ticks / TicksPerDay + 1; // Calculate the appromixate Persian Year. long yearStart = CalendricalCalculationsHelper.PersianNewYearOnOrBefore(numDays); @@ -197,7 +197,7 @@ internal void GetDate(long ticks, out int year, out int month, out int day) // Get the absolute date. The absolute date is the number of days from January 1st, 1 A.D. // 1/1/0001 is absolute date 1. - long numDays = ticks / GregorianCalendar.TicksPerDay + 1; + long numDays = ticks / TicksPerDay + 1; // Calculate the appromixate Persian Year. long yearStart = CalendricalCalculationsHelper.PersianNewYearOnOrBefore(numDays); @@ -246,7 +246,7 @@ public override DateTime AddMonths(DateTime time, int months) } long ticks = GetAbsoluteDatePersian(y, m, d) * TicksPerDay + time.Ticks % TicksPerDay; - Calendar.CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime); + CheckAddResult(ticks, MinSupportedDateTime, MaxSupportedDateTime); return new DateTime(ticks); } @@ -384,7 +384,7 @@ public override DateTime ToDateTime(int year, int month, int day, int hour, int throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay); } - return new DateTime(lDate * GregorianCalendar.TicksPerDay + TimeToTicks(hour, minute, second, millisecond)); + return new DateTime(lDate * TicksPerDay + TimeToTicks(hour, minute, second, millisecond)); } private const int DefaultTwoDigitYearMax = 1410; diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/StringInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/StringInfo.cs index f527d59545f3f0..bd3b769124bc79 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/StringInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/StringInfo.cs @@ -45,7 +45,7 @@ private int[]? Indexes { if (_indexes == null && String.Length > 0) { - _indexes = StringInfo.ParseCombiningCharacters(String); + _indexes = ParseCombiningCharacters(String); } return _indexes; 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 5b35c0d6ede5ce..ad8340b0bc848c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/TimeSpanFormat.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/TimeSpanFormat.cs @@ -12,8 +12,8 @@ namespace System.Globalization { internal static class TimeSpanFormat { - internal static readonly FormatLiterals PositiveInvariantFormatLiterals = TimeSpanFormat.FormatLiterals.InitInvariant(isNegative: false); - internal static readonly FormatLiterals NegativeInvariantFormatLiterals = TimeSpanFormat.FormatLiterals.InitInvariant(isNegative: true); + internal static readonly FormatLiterals PositiveInvariantFormatLiterals = FormatLiterals.InitInvariant(isNegative: false); + internal static readonly FormatLiterals NegativeInvariantFormatLiterals = FormatLiterals.InitInvariant(isNegative: true); /// Main method called from TimeSpan.ToString. internal static string Format(TimeSpan value, string? format, IFormatProvider? formatProvider) diff --git a/src/libraries/System.Private.CoreLib/src/System/Globalization/UmAlQuraCalendar.cs b/src/libraries/System.Private.CoreLib/src/System/Globalization/UmAlQuraCalendar.cs index f5dabc3bcaba1c..762c248f468819 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Globalization/UmAlQuraCalendar.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Globalization/UmAlQuraCalendar.cs @@ -341,7 +341,7 @@ private static void ConvertGregorianToHijri(DateTime time, out int HijriYear, ou // Find the index where we should start our search by quessing the Hijri year that we will be in HijriYearInfo. // A Hijri year is 354 or 355 days. Use 355 days so that we will search from a lower index. - int index = (int)((time.Ticks - s_minDate.Ticks) / Calendar.TicksPerDay) / 355; + int index = (int)((time.Ticks - s_minDate.Ticks) / TicksPerDay) / 355; do { } while (time.CompareTo(s_hijriYearInfo[++index].GregorianDate) > 0); // while greater @@ -445,7 +445,7 @@ public override DateTime AddMonths(DateTime time, int months) CheckYearRange(y, UmAlQuraEra); DateTime dt = new DateTime(GetAbsoluteDateUmAlQura(y, m, d) * TicksPerDay + time.Ticks % TicksPerDay); - Calendar.CheckAddResult(dt.Ticks, MinSupportedDateTime, MaxSupportedDateTime); + CheckAddResult(dt.Ticks, MinSupportedDateTime, MaxSupportedDateTime); return dt; } @@ -591,7 +591,7 @@ public override DateTime ToDateTime(int year, int month, int day, int hour, int throw new ArgumentOutOfRangeException(null, SR.ArgumentOutOfRange_BadYearMonthDay); } - return new DateTime(lDate * GregorianCalendar.TicksPerDay + TimeToTicks(hour, minute, second, millisecond)); + return new DateTime(lDate * TicksPerDay + TimeToTicks(hour, minute, second, millisecond)); } private const int DefaultTwoDigitYearMax = 1451; diff --git a/src/libraries/System.Private.CoreLib/src/System/Guid.cs b/src/libraries/System.Private.CoreLib/src/System/Guid.cs index 8fd0da14bd6c62..fc847e403ac4ab 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Guid.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Guid.cs @@ -849,7 +849,7 @@ public byte[] ToByteArray() var g = new byte[16]; if (BitConverter.IsLittleEndian) { - MemoryMarshal.TryWrite(g, ref Unsafe.AsRef(in this)); + MemoryMarshal.TryWrite(g, ref Unsafe.AsRef(in this)); } else { diff --git a/src/libraries/System.Private.CoreLib/src/System/Half.cs b/src/libraries/System.Private.CoreLib/src/System/Half.cs index b462c88b6e3908..6415acc9c798e3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Half.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Half.cs @@ -281,7 +281,7 @@ public static bool IsSubnormal(Half value) /// Parses a from a in the default parse style. /// /// The input to be parsed. - /// The equivalent value representing the input string. If the input exceeds Half's range, a or is returned. + /// The equivalent value representing the input string. If the input exceeds Half's range, a or is returned. public static Half Parse(string s) { if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); @@ -293,7 +293,7 @@ public static Half Parse(string s) /// /// The input to be parsed. /// The used to parse the input. - /// The equivalent value representing the input string. If the input exceeds Half's range, a or is returned. + /// The equivalent value representing the input string. If the input exceeds Half's range, a or is returned. public static Half Parse(string s, NumberStyles style) { NumberFormatInfo.ValidateParseStyleFloatingPoint(style); @@ -306,7 +306,7 @@ public static Half Parse(string s, NumberStyles style) /// /// The input to be parsed. /// A format provider. - /// The equivalent value representing the input string. If the input exceeds Half's range, a or is returned. + /// The equivalent value representing the input string. If the input exceeds Half's range, a or is returned. public static Half Parse(string s, IFormatProvider? provider) { if (s == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); @@ -319,7 +319,7 @@ public static Half Parse(string s, IFormatProvider? provider) /// The input to be parsed. /// The used to parse the input. /// A format provider. - /// The equivalent value representing the input string. If the input exceeds Half's range, a or is returned. + /// The equivalent value representing the input string. If the input exceeds Half's range, a or is returned. public static Half Parse(string s, NumberStyles style = DefaultParseStyle, IFormatProvider? provider = null) { NumberFormatInfo.ValidateParseStyleFloatingPoint(style); @@ -333,7 +333,7 @@ public static Half Parse(string s, NumberStyles style = DefaultParseStyle, IForm /// The input to be parsed. /// The used to parse the input. /// A format provider. - /// The equivalent value representing the input string. If the input exceeds Half's range, a or is returned. + /// The equivalent value representing the input string. If the input exceeds Half's range, a or is returned. public static Half Parse(ReadOnlySpan s, NumberStyles style = DefaultParseStyle, IFormatProvider? provider = null) { NumberFormatInfo.ValidateParseStyleFloatingPoint(style); @@ -344,7 +344,7 @@ public static Half Parse(ReadOnlySpan s, NumberStyles style = DefaultParse /// Tries to parse a from a in the default parse style. /// /// The input to be parsed. - /// The equivalent value representing the input string if the parse was successful. If the input exceeds Half's range, a or is returned. If the parse was unsuccessful, a default value is returned. + /// The equivalent value representing the input string if the parse was successful. If the input exceeds Half's range, a or is returned. If the parse was unsuccessful, a default value is returned. /// if the parse was successful, otherwise. public static bool TryParse([NotNullWhen(true)] string? s, out Half result) { @@ -360,7 +360,7 @@ public static bool TryParse([NotNullWhen(true)] string? s, out Half result) /// Tries to parse a from a in the default parse style. /// /// The input to be parsed. - /// The equivalent value representing the input string if the parse was successful. If the input exceeds Half's range, a or is returned. If the parse was unsuccessful, a default value is returned. + /// The equivalent value representing the input string if the parse was successful. If the input exceeds Half's range, a or is returned. If the parse was unsuccessful, a default value is returned. /// if the parse was successful, otherwise. public static bool TryParse(ReadOnlySpan s, out Half result) { @@ -373,7 +373,7 @@ public static bool TryParse(ReadOnlySpan s, out Half result) /// The input to be parsed. /// The used to parse the input. /// A format provider. - /// The equivalent value representing the input string if the parse was successful. If the input exceeds Half's range, a or is returned. If the parse was unsuccessful, a default value is returned. + /// The equivalent value representing the input string if the parse was successful. If the input exceeds Half's range, a or is returned. If the parse was unsuccessful, a default value is returned. /// if the parse was successful, otherwise. public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out Half result) { @@ -394,7 +394,7 @@ public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, I /// The input to be parsed. /// The used to parse the input. /// A format provider. - /// The equivalent value representing the input string if the parse was successful. If the input exceeds Half's range, a or is returned. If the parse was unsuccessful, a default value is returned. + /// The equivalent value representing the input string if the parse was successful. If the input exceeds Half's range, a or is returned. If the parse was unsuccessful, a default value is returned. /// if the parse was successful, otherwise. public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatProvider? provider, out Half result) { @@ -1651,21 +1651,21 @@ public static Half MinMagnitudeNumber(Half x, Half y) [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out Half result) { - return TryConvertFrom(value, out result); + return TryConvertFrom(value, out result); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromSaturating(TOther value, out Half result) { - return TryConvertFrom(value, out result); + return TryConvertFrom(value, out result); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromTruncating(TOther value, out Half result) { - return TryConvertFrom(value, out result); + return TryConvertFrom(value, out result); } private static bool TryConvertFrom(TOther value, out Half result) @@ -1807,14 +1807,14 @@ static bool INumberBase.TryConvertToChecked(Half value, [MaybeNull [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertToSaturating(Half value, [MaybeNullWhen(false)] out TOther result) { - return TryConvertTo(value, out result); + return TryConvertTo(value, out result); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertToTruncating(Half value, [MaybeNullWhen(false)] out TOther result) { - return TryConvertTo(value, out result); + return TryConvertTo(value, out result); } private static bool TryConvertTo(Half value, [MaybeNullWhen(false)] out TOther result) diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/DirectoryNotFoundException.cs b/src/libraries/System.Private.CoreLib/src/System/IO/DirectoryNotFoundException.cs index dade7b3a68a64c..0fe377e665456c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/DirectoryNotFoundException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/DirectoryNotFoundException.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.IO @@ -13,7 +14,7 @@ namespace System.IO * and STG_E_PATHNOTFOUND (0x80030003). */ [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class DirectoryNotFoundException : IOException { public DirectoryNotFoundException() diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/EndOfStreamException.cs b/src/libraries/System.Private.CoreLib/src/System/IO/EndOfStreamException.cs index 7bd422ba220c19..bc3e2e07fe2541 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/EndOfStreamException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/EndOfStreamException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.IO { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class EndOfStreamException : IOException { public EndOfStreamException() diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Windows.cs index 27a15cb6c192bc..d485394093b834 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.Windows.cs @@ -6,7 +6,7 @@ namespace System.IO.Enumeration { - /// Provides a lower level view of to help process and filter find results. + /// Provides a lower level view of to help process and filter find results. public unsafe ref partial struct FileSystemEntry { internal static void Initialize( @@ -66,8 +66,8 @@ internal static void Initialize( /// if the file has the hidden attribute; otherwise, . public bool IsHidden => (Attributes & FileAttributes.Hidden) != 0; - /// Converts the value of this instance to a . - /// The value of this instance as a . + /// Converts the value of this instance to a . + /// The value of this instance as a . public FileSystemInfo ToFileSystemInfo() => FileSystemInfo.Create(Path.Join(Directory, FileName), ref this); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.cs index bea0714fdf2117..d6eaf8ea1b0788 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEntry.cs @@ -6,7 +6,7 @@ namespace System.IO.Enumeration { - /// Provides a lower level view of to help process and filter find results. + /// Provides a lower level view of to help process and filter find results. public ref partial struct FileSystemEntry { /// Returns the full path for the find results, based on the initially provided path. diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs index ff60da928bfd0c..47acd695a01ce9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.Windows.cs @@ -13,7 +13,7 @@ namespace System.IO.Enumeration { - /// Enumerates the file system elements of the provided type that are being searched and filtered by a . + /// Enumerates the file system elements of the provided type that are being searched and filtered by a . public abstract unsafe partial class FileSystemEnumerator : CriticalFinalizerObject, IEnumerator { private const int StandardBufferSize = 4096; @@ -203,7 +203,7 @@ private bool ContinueOnDirectoryError(int error, bool ignoreNotFound) || ContinueOnError(error); } - /// Advances the enumerator to the next item of the . + /// Advances the enumerator to the next item of the . /// if the enumerator successfully advanced to the next item; if the end of the enumerator has been passed. public bool MoveNext() { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.cs index bca11da56ee711..d41895e97728ed 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemEnumerator.cs @@ -72,7 +72,7 @@ protected virtual void OnDirectoryFinished(ReadOnlySpan directory) { } /// Gets the currently visited object. /// The currently visited object. - /// This member is an explicit interface member implementation. It can be used only when the instance is cast to an interface. + /// This member is an explicit interface member implementation. It can be used only when the instance is cast to an interface. object? IEnumerator.Current => Current; private void DirectoryFinished() @@ -94,20 +94,20 @@ private void DirectoryFinished() } } - /// Always throws . + /// Always throws . public void Reset() { throw new NotSupportedException(); } - /// Releases the resources used by the current instance of the class. + /// Releases the resources used by the current instance of the class. public void Dispose() { InternalDispose(disposing: true); GC.SuppressFinalize(this); } - /// When overridden in a derived class, releases the unmanaged resources used by the class and optionally releases the managed resources. + /// When overridden in a derived class, releases the unmanaged resources used by the class and optionally releases the managed resources. /// to release both managed and unmanaged resources; to release only unmanaged resources. protected virtual void Dispose(bool disposing) { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemName.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemName.cs index b958d1e45f7d6e..1ecb3b0373578a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemName.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Enumeration/FileSystemName.cs @@ -60,7 +60,7 @@ public static string TranslateWin32Expression(string? expression) /// to ignore case (default), if the match should be case-sensitive. /// if the given expression matches the given name; otherwise, . /// The syntax of the parameter is based on the syntax used by FileSystemWatcher, which is based on [RtlIsNameInExpression](/windows/win32/devnotes/rtlisnameinexpression), which defines the rules for matching DOS wildcards (`'*'`, `'?'`, `'<'`, `'>'`, `'"'`). - /// Matching will not correspond to Win32 behavior unless you transform the expression using . + /// Matching will not correspond to Win32 behavior unless you transform the expression using . public static bool MatchesWin32Expression(ReadOnlySpan expression, ReadOnlySpan name, bool ignoreCase = true) { return MatchPattern(expression, name, ignoreCase, useExtendedWildcards: true); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/EnumerationOptions.cs b/src/libraries/System.Private.CoreLib/src/System/IO/EnumerationOptions.cs index 8a31939444be4e..5701e79e057584 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/EnumerationOptions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/EnumerationOptions.cs @@ -51,7 +51,7 @@ internal static EnumerationOptions FromSearchOption(SearchOption searchOption) /// to recurse into subdirectories; otherwise, . public bool RecurseSubdirectories { get; set; } - /// Gets or sets a value that indicates whether to skip files or directories when access is denied (for example, or ). The default is . + /// Gets or sets a value that indicates whether to skip files or directories when access is denied (for example, or ). The default is . /// to skip innacessible files or directories; otherwise, . public bool IgnoreInaccessible { get; set; } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs index ca68bb7414b733..84e8aa18df8a04 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/File.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/File.cs @@ -121,7 +121,7 @@ public static bool Exists([NotNullWhen(true)] string? path) /// /// Initializes a new instance of the class with the specified path, creation mode, read/write and sharing permission, the access other FileStreams can have to the same file, the buffer size, additional file options and the allocation size. /// - /// for information about exceptions. + /// for information about exceptions. public static FileStream Open(string path, FileStreamOptions options) => new FileStream(path, options); public static FileStream Open(string path, FileMode mode) @@ -134,15 +134,15 @@ public static FileStream Open(string path, FileMode mode, FileAccess access, Fil => new FileStream(path, mode, access, share); /// - /// Initializes a new instance of the class with the specified path, creation mode, read/write and sharing permission, the access other SafeFileHandles can have to the same file, additional file options and the allocation size. + /// Initializes a new instance of the class with the specified path, creation mode, read/write and sharing permission, the access other SafeFileHandles can have to the same file, additional file options and the allocation size. /// - /// A relative or absolute path for the file that the current instance will encapsulate. + /// A relative or absolute path for the file that the current instance will encapsulate. /// One of the enumeration values that determines how to open or create the file. The default value is /// A bitwise combination of the enumeration values that determines how the file can be accessed. The default value is /// A bitwise combination of the enumeration values that determines how the file will be shared by processes. The default value is . /// The initial allocation size in bytes for the file. A positive value is effective only when a regular file is being created, overwritten, or replaced. /// Negative values are not allowed. In other cases (including the default 0 value), it's ignored. - /// An object that describes optional parameters to use. + /// An object that describes optional parameters to use. /// is . /// is an empty string (""), contains only white space, or contains one or more invalid characters. /// -or- diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.cs index 0cc990dc2fed2a..ac0b6c3fccbcee 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileInfo.cs @@ -72,9 +72,9 @@ public bool IsReadOnly } /// - /// Initializes a new instance of the class with the specified creation mode, read/write and sharing permission, the access other FileStreams can have to the same file, the buffer size, additional file options and the allocation size. + /// Initializes a new instance of the class with the specified creation mode, read/write and sharing permission, the access other FileStreams can have to the same file, the buffer size, additional file options and the allocation size. /// - /// for information about exceptions. + /// for information about exceptions. public FileStream Open(FileStreamOptions options) => File.Open(NormalizedPath, options); public StreamReader OpenText() diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileLoadException.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileLoadException.cs index 816b90577eee85..2413ce80c2b0a3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileLoadException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileLoadException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.IO { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public partial class FileLoadException : IOException { public FileLoadException() diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileNotFoundException.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileNotFoundException.cs index 569dc1850b9ff2..1175b9c9fcda0b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileNotFoundException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileNotFoundException.cs @@ -3,13 +3,14 @@ using System.ComponentModel; using System.Diagnostics; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.IO { // Thrown when trying to access a file that doesn't exist on disk. [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public partial class FileNotFoundException : IOException { public FileNotFoundException() @@ -59,7 +60,7 @@ private void SetMessageField() if (_message == null) { if ((FileName == null) && - (HResult == System.HResults.COR_E_EXCEPTION)) + (HResult == HResults.COR_E_EXCEPTION)) _message = SR.IO_FileNotFound; else if (FileName != null) _message = FileLoadException.FormatFileLoadExceptionMessage(FileName, HResult); diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs index d7e940f62e8b47..67dd7bd2845832 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileStream.cs @@ -156,28 +156,28 @@ public FileStream(string path, FileMode mode, FileAccess access, FileShare share } /// - /// Initializes a new instance of the class with the specified path, creation mode, read/write and sharing permission, the access other FileStreams can have to the same file, the buffer size, additional file options and the allocation size. + /// Initializes a new instance of the class with the specified path, creation mode, read/write and sharing permission, the access other FileStreams can have to the same file, the buffer size, additional file options and the allocation size. /// - /// A relative or absolute path for the file that the current instance will encapsulate. - /// An object that describes optional parameters to use. + /// A relative or absolute path for the file that the current instance will encapsulate. + /// An object that describes optional parameters to use. /// or is . /// is an empty string (""), contains only white space, or contains one or more invalid characters. /// -or- /// refers to a non-file device, such as CON:, COM1:, LPT1:, etc. in an NTFS environment. /// refers to a non-file device, such as CON:, COM1:, LPT1:, etc. in a non-NTFS environment. - /// The file cannot be found, such as when is or , and the file specified by does not exist. The file must already exist in these modes. + /// The file cannot be found, such as when is or , and the file specified by does not exist. The file must already exist in these modes. /// An I/O error, such as specifying when the file specified by already exists, occurred. /// -or- /// The stream has been closed. /// -or- - /// The disk was full (when was provided and was pointing to a regular file). + /// The disk was full (when was provided and was pointing to a regular file). /// -or- - /// The file was too large (when was provided and was pointing to a regular file). + /// The file was too large (when was provided and was pointing to a regular file). /// The caller does not have the required permission. /// The specified path is invalid, such as being on an unmapped drive. - /// The requested is not permitted by the operating system for the specified , such as when is or and the file or directory is set for read-only access. + /// The requested is not permitted by the operating system for the specified , such as when is or and the file or directory is set for read-only access. /// -or- - /// is specified for , but file encryption is not supported on the current platform. + /// is specified for , but file encryption is not supported on the current platform. /// The specified path, file name, or both exceed the system-defined maximum length. public FileStream(string path, FileStreamOptions options) { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileStreamOptions.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileStreamOptions.cs index 333b864c5c8d14..3ad88fcc8d8e24 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileStreamOptions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileStreamOptions.cs @@ -34,7 +34,7 @@ public FileMode Mode } /// - /// A bitwise combination of the enumeration values that determines how the file can be accessed by the object. This also determines the values returned by the and properties of the object. + /// A bitwise combination of the enumeration values that determines how the file can be accessed by the object. This also determines the values returned by the and properties of the object. /// /// When contains an invalid value. public FileAccess Access @@ -52,7 +52,7 @@ public FileAccess Access } /// - /// A bitwise combination of the enumeration values that determines how the file will be shared by processes. The default value is . + /// A bitwise combination of the enumeration values that determines how the file will be shared by processes. The default value is . /// /// When contains an invalid value. public FileShare Share @@ -72,7 +72,7 @@ public FileShare Share } /// - /// A bitwise combination of the enumeration values that specifies additional file options. The default value is , which indicates synchronous IO. + /// A bitwise combination of the enumeration values that specifies additional file options. The default value is , which indicates synchronous IO. /// /// When contains an invalid value. public FileOptions Options diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.cs b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.cs index 6c4242dfa4cf23..e8344b6d06f4ba 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/FileSystemInfo.cs @@ -136,7 +136,7 @@ public string? LinkTarget /// /// The value may be cached when either the value itself or other properties are accessed. To get the latest value, call the method. /// - /// If the path doesn't exist as of the last cached state, the return value is `(UnixFileMode)(-1)`. or can only be thrown when setting the value. + /// If the path doesn't exist as of the last cached state, the return value is `(UnixFileMode)(-1)`. or can only be thrown when setting the value. /// public UnixFileMode UnixFileMode { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/IOException.cs b/src/libraries/System.Private.CoreLib/src/System/IO/IOException.cs index 0cbaac41038f11..07dadbe6c206ec 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/IOException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/IOException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.IO { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class IOException : SystemException { public IOException() diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/InvalidDataException.cs b/src/libraries/System.Private.CoreLib/src/System/IO/InvalidDataException.cs index 2907219cc1e859..d928c92170aa13 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/InvalidDataException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/InvalidDataException.cs @@ -1,36 +1,37 @@ // 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.Serialization; namespace System.IO { /// The exception that is thrown when a data stream is in an invalid format. - /// An is thrown when invalid data is detected in the data stream. + /// An is thrown when invalid data is detected in the data stream. [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class InvalidDataException : SystemException { - /// Initializes a new instance of the class. - /// This constructor initializes the property of the new instance to a system-supplied message that describes the error, such as "An invalid argument was specified." This message is localized based on the current system culture. + /// Initializes a new instance of the class. + /// This constructor initializes the property of the new instance to a system-supplied message that describes the error, such as "An invalid argument was specified." This message is localized based on the current system culture. public InvalidDataException() : base(SR.GenericInvalidData) { } - /// Initializes a new instance of the class with a specified error message. + /// Initializes a new instance of the class with a specified error message. /// The error message that explains the reason for the exception. - /// This constructor initializes the property of the new instance to a system-supplied message that describes the error, such as "An invalid argument was specified." This message is localized based on the current system culture. + /// This constructor initializes the property of the new instance to a system-supplied message that describes the error, such as "An invalid argument was specified." This message is localized based on the current system culture. public InvalidDataException(string? message) : base(message) { } - /// Initializes a new instance of the class with a reference to the inner exception that is the cause of this exception. + /// Initializes a new instance of the class with a reference to the inner exception that is the cause of this exception. /// The error message that explains the reason for the exception. /// The exception that is the cause of the current exception. If the parameter is not , the current exception is raised in a block that handles the inner exception. - /// This constructor initializes the property of the new instance using the value of the parameter. The content of the parameter is intended to be understood by humans. The caller of this constructor is required to ensure that this string has been localized for the current system culture. - /// An exception that is thrown as a direct result of a previous exception should include a reference to the previous exception in the property. The property returns the same value that is passed into the constructor, or if the property does not supply the inner exception value to the constructor. + /// This constructor initializes the property of the new instance using the value of the parameter. The content of the parameter is intended to be understood by humans. The caller of this constructor is required to ensure that this string has been localized for the current system culture. + /// An exception that is thrown as a direct result of a previous exception should include a reference to the previous exception in the property. The property returns the same value that is passed into the constructor, or if the property does not supply the inner exception value to the constructor. public InvalidDataException(string? message, Exception? innerException) : base(message, innerException) { diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/MatchType.cs b/src/libraries/System.Private.CoreLib/src/System/IO/MatchType.cs index d157b13ad5ac43..97f6e575412d26 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/MatchType.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/MatchType.cs @@ -7,7 +7,7 @@ namespace System.IO public enum MatchType { /// Matches using '*' and '?' wildcards. - /// * matches from zero to any amount of characters. ? matches exactly one character. *.* matches any name with a period in it (with , this would match all items). + /// * matches from zero to any amount of characters. ? matches exactly one character. *.* matches any name with a period in it (with , this would match all items). Simple, /// Match using Win32 DOS style matching semantics.'*', '?', '<', '>', and '"' are all considered wildcards. Matches in a traditional DOS / Windows command prompt way. *.* matches all files. ? matches collapse to periods. file.??t will match file.t, file.at, and file.txt. diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/Path.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/IO/Path.Windows.cs index 8f31c70c96cb86..e5ee3e8fec49f0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Path.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Path.Windows.cs @@ -245,7 +245,7 @@ public static string GetTempFileName() span[7] = (char)Base32Char[((b0 & 0b1110_0000) >> 5) | ((b1 & 0b1100_0000) >> 3)]; span[8] = (char)Base32Char[((b2 & 0b1110_0000) >> 5) | ((b3 & 0b1100_0000) >> 3)]; - string path = string.Concat(Path.GetTempPath(), span); + string path = string.Concat(GetTempPath(), span); try { @@ -334,7 +334,7 @@ internal static ReadOnlySpan GetVolumeName(ReadOnlySpan path) } ReadOnlySpan pathToTrim = root.Slice(startOffset); - return Path.EndsInDirectorySeparator(pathToTrim) ? pathToTrim.Slice(0, pathToTrim.Length - 1) : pathToTrim; + return EndsInDirectorySeparator(pathToTrim) ? pathToTrim.Slice(0, pathToTrim.Length - 1) : pathToTrim; } /// 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 be8ea99c30cb72..9d1dced98c8c0b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Path.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Path.cs @@ -293,7 +293,7 @@ public static unsafe string GetRandomFileName() /// /// /// Handles paths that use the alternate directory separator. It is a frequent mistake to - /// assume that rooted paths are not relative. This isn't the case. + /// assume that rooted paths are not relative. This isn't the case. /// "C:a" is drive relative- meaning that it will be resolved against the current directory /// for C: (rooted, but relative). "C:\a" is rooted and not relative (the current directory /// will not be used to modify the path). diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/PathTooLongException.cs b/src/libraries/System.Private.CoreLib/src/System/IO/PathTooLongException.cs index e5b66894f95bf6..280d59991556e9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/PathTooLongException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/PathTooLongException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.IO { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class PathTooLongException : IOException { public PathTooLongException() 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 8c1c9bb1f1845f..86d01528643b27 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/Stream.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/Stream.cs @@ -686,7 +686,7 @@ public ReadWriteTask( { _callback = callback; _context = ExecutionContext.Capture(); - base.AddCompletionAction(this); + AddCompletionAction(this); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryAccessor.cs b/src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryAccessor.cs index a8a56e86cbd782..488bb1e09ea3e6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryAccessor.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/UnmanagedMemoryAccessor.cs @@ -361,7 +361,7 @@ public int ReadArray(long position, T[] array, int offset, int count) where T } } - _buffer.ReadArray((ulong)(_offset + position), array, offset, n); + _buffer.ReadArray((ulong)(_offset + position), array, offset, n); return n; } @@ -406,7 +406,7 @@ public void Write(long position, short value) try { _buffer.AcquirePointer(ref pointer); - Unsafe.WriteUnaligned(pointer + _offset + position, value); + Unsafe.WriteUnaligned(pointer + _offset + position, value); } finally { @@ -429,7 +429,7 @@ public void Write(long position, int value) try { _buffer.AcquirePointer(ref pointer); - Unsafe.WriteUnaligned(pointer + _offset + position, value); + Unsafe.WriteUnaligned(pointer + _offset + position, value); } finally { @@ -452,7 +452,7 @@ public void Write(long position, long value) try { _buffer.AcquirePointer(ref pointer); - Unsafe.WriteUnaligned(pointer + _offset + position, value); + Unsafe.WriteUnaligned(pointer + _offset + position, value); } finally { @@ -480,10 +480,10 @@ public void Write(long position, decimal value) _buffer.AcquirePointer(ref pointer); pointer += (_offset + position); - Unsafe.WriteUnaligned(pointer, bits[0]); - Unsafe.WriteUnaligned(pointer + 4, bits[1]); - Unsafe.WriteUnaligned(pointer + 8, bits[2]); - Unsafe.WriteUnaligned(pointer + 12, bits[3]); + Unsafe.WriteUnaligned(pointer, bits[0]); + Unsafe.WriteUnaligned(pointer + 4, bits[1]); + Unsafe.WriteUnaligned(pointer + 8, bits[2]); + Unsafe.WriteUnaligned(pointer + 12, bits[3]); } finally { @@ -540,7 +540,7 @@ public void Write(long position, ref T structure) where T : struct } } - _buffer.Write((ulong)(_offset + position), structure); + _buffer.Write((ulong)(_offset + position), structure); } // Writes 'count' structs of type T from 'array' (starting at 'offset') into unmanaged memory. @@ -569,7 +569,7 @@ public void WriteArray(long position, T[] array, int offset, int count) where throw new NotSupportedException(SR.NotSupported_Writing); } - _buffer.WriteArray((ulong)(_offset + position), array, offset, count); + _buffer.WriteArray((ulong)(_offset + position), array, offset, count); } private void EnsureSafeToRead(long position, int sizeOfType) diff --git a/src/libraries/System.Private.CoreLib/src/System/IndexOutOfRangeException.cs b/src/libraries/System.Private.CoreLib/src/System/IndexOutOfRangeException.cs index 2a900f8d24be1b..bcd865853837bc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IndexOutOfRangeException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IndexOutOfRangeException.cs @@ -10,12 +10,13 @@ ** =============================================================================*/ +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class IndexOutOfRangeException : SystemException { public IndexOutOfRangeException() diff --git a/src/libraries/System.Private.CoreLib/src/System/InsufficientExecutionStackException.cs b/src/libraries/System.Private.CoreLib/src/System/InsufficientExecutionStackException.cs index 57479d9279ad6f..b6a8d865055ad9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/InsufficientExecutionStackException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/InsufficientExecutionStackException.cs @@ -1,12 +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.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class InsufficientExecutionStackException : SystemException { public InsufficientExecutionStackException() diff --git a/src/libraries/System.Private.CoreLib/src/System/InsufficientMemoryException.cs b/src/libraries/System.Private.CoreLib/src/System/InsufficientMemoryException.cs index e6681690a642ee..c2ba90170cf9f9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/InsufficientMemoryException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/InsufficientMemoryException.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System @@ -14,7 +15,7 @@ namespace System /// want to recover from these errors. /// [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class InsufficientMemoryException : OutOfMemoryException { public InsufficientMemoryException() : base( diff --git a/src/libraries/System.Private.CoreLib/src/System/InvalidCastException.cs b/src/libraries/System.Private.CoreLib/src/System/InvalidCastException.cs index 867c7bb97cc1bd..9a8df55017d055 100644 --- a/src/libraries/System.Private.CoreLib/src/System/InvalidCastException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/InvalidCastException.cs @@ -8,12 +8,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class InvalidCastException : SystemException { public InvalidCastException() diff --git a/src/libraries/System.Private.CoreLib/src/System/InvalidOperationException.cs b/src/libraries/System.Private.CoreLib/src/System/InvalidOperationException.cs index 8ac60234798dea..20cf8a66cb5096 100644 --- a/src/libraries/System.Private.CoreLib/src/System/InvalidOperationException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/InvalidOperationException.cs @@ -12,12 +12,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class InvalidOperationException : SystemException { public InvalidOperationException() diff --git a/src/libraries/System.Private.CoreLib/src/System/InvalidProgramException.cs b/src/libraries/System.Private.CoreLib/src/System/InvalidProgramException.cs index b4cdf72787ce94..675dc6597e62ef 100644 --- a/src/libraries/System.Private.CoreLib/src/System/InvalidProgramException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/InvalidProgramException.cs @@ -10,12 +10,13 @@ ** =============================================================================*/ +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class InvalidProgramException : SystemException { public InvalidProgramException() diff --git a/src/libraries/System.Private.CoreLib/src/System/InvalidTimeZoneException.cs b/src/libraries/System.Private.CoreLib/src/System/InvalidTimeZoneException.cs index 6ad67475a41d0d..d42632e56ab0fd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/InvalidTimeZoneException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/InvalidTimeZoneException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class InvalidTimeZoneException : Exception { public InvalidTimeZoneException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Lazy.cs b/src/libraries/System.Private.CoreLib/src/System/Lazy.cs index 80d52f297cc9f2..f7be79c8201148 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Lazy.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Lazy.cs @@ -198,7 +198,7 @@ public class Lazy<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Pub private T? _value; /// - /// Initializes a new instance of the class that + /// Initializes a new instance of the class that /// uses 's default constructor for lazy initialization. /// /// @@ -210,7 +210,7 @@ public Lazy() } /// - /// Initializes a new instance of the class that + /// Initializes a new instance of the class that /// uses a pre-initialized specified value. /// /// @@ -223,14 +223,14 @@ public Lazy(T value) } /// - /// Initializes a new instance of the class that uses a + /// Initializes a new instance of the class that uses a /// specified initialization function. /// /// - /// The invoked to produce the lazily-initialized value when it is + /// The invoked to produce the lazily-initialized value when it is /// needed. /// - /// is a null + /// is a null /// reference (Nothing in Visual Basic). /// /// An instance created with this constructor may be used concurrently from multiple threads. @@ -241,7 +241,7 @@ public Lazy(Func valueFactory) } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class that uses 's default constructor and a specified thread-safety mode. /// /// true if this instance should be usable by multiple threads concurrently; false if the instance will only be used by one thread at a time. @@ -252,26 +252,26 @@ public Lazy(bool isThreadSafe) : } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class that uses 's default constructor and a specified thread-safety mode. /// /// The lazy thread-safety mode - /// mode contains an invalid valuee + /// mode contains an invalid valuee public Lazy(LazyThreadSafetyMode mode) : this(null, mode, useDefaultConstructor: true) { } /// - /// Initializes a new instance of the class + /// Initializes a new instance of the class /// that uses a specified initialization function and a specified thread-safety mode. /// /// - /// The invoked to produce the lazily-initialized value when it is needed. + /// The invoked to produce the lazily-initialized value when it is needed. /// /// true if this instance should be usable by multiple threads concurrently; false if the instance will only be used by one thread at a time. /// - /// is + /// is /// a null reference (Nothing in Visual Basic). public Lazy(Func valueFactory, bool isThreadSafe) : this(valueFactory, LazyHelper.GetModeFromIsThreadSafe(isThreadSafe), useDefaultConstructor: false) @@ -279,16 +279,16 @@ public Lazy(Func valueFactory, bool isThreadSafe) : } /// - /// Initializes a new instance of the class + /// Initializes a new instance of the class /// that uses a specified initialization function and a specified thread-safety mode. /// /// - /// The invoked to produce the lazily-initialized value when it is needed. + /// The invoked to produce the lazily-initialized value when it is needed. /// /// The lazy thread-safety mode. - /// is + /// is /// a null reference (Nothing in Visual Basic). - /// mode contains an invalid value. + /// mode contains an invalid value. public Lazy(Func valueFactory, LazyThreadSafetyMode mode) : this(valueFactory, mode, useDefaultConstructor: false) { @@ -438,7 +438,7 @@ private T CreateValue() /// Creates and returns a string representation of this instance. /// The result of calling on the . - /// + /// /// The is null. /// public override string? ToString() @@ -471,36 +471,36 @@ internal T? ValueForDebugDisplay /// internal bool IsValueFaulted => LazyHelper.GetIsValueFaulted(_state); - /// Gets a value indicating whether the has been initialized. + /// Gets a value indicating whether the has been initialized. /// - /// true if the instance has been initialized; + /// true if the instance has been initialized; /// otherwise, false. /// - /// The initialization of a instance may result in either + /// The initialization of a instance may result in either /// a value being produced or an exception being thrown. If an exception goes unhandled during initialization, /// will return false. /// public bool IsValueCreated => _state == null; /// Gets the lazily initialized value of the current . + /// cref="Lazy{T}"/>. /// The lazily initialized value of the current . - /// - /// The was initialized to use the default constructor + /// cref="Lazy{T}"/>. + /// + /// The was initialized to use the default constructor /// of the type being lazily initialized, and that type does not have a public, parameterless constructor. /// - /// - /// The was initialized to use the default constructor + /// + /// The was initialized to use the default constructor /// of the type being lazily initialized, and permissions to access the constructor were missing. /// - /// - /// The was constructed with the or - /// and the initialization function attempted to access on this instance. + /// + /// The was constructed with the or + /// and the initialization function attempted to access on this instance. /// /// /// If is false, accessing will force initialization. - /// Please for more information on how will behave if an exception is thrown + /// Please for more information on how will behave if an exception is thrown /// from initialization delegate. /// [DebuggerBrowsable(DebuggerBrowsableState.Never)] diff --git a/src/libraries/System.Private.CoreLib/src/System/LoaderOptimization.cs b/src/libraries/System.Private.CoreLib/src/System/LoaderOptimization.cs index 36ae579f165d36..f2f381234e553c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/LoaderOptimization.cs +++ b/src/libraries/System.Private.CoreLib/src/System/LoaderOptimization.cs @@ -5,9 +5,9 @@ namespace System { public enum LoaderOptimization { - [System.ObsoleteAttribute("LoaderOptimization.DisallowBindings has been deprecated and is not supported.")] + [Obsolete("LoaderOptimization.DisallowBindings has been deprecated and is not supported.")] DisallowBindings = 4, - [System.ObsoleteAttribute("LoaderOptimization.DomainMask has been deprecated and is not supported.")] + [Obsolete("LoaderOptimization.DomainMask has been deprecated and is not supported.")] DomainMask = 3, MultiDomain = 2, MultiDomainHost = 3, diff --git a/src/libraries/System.Private.CoreLib/src/System/MarshalByRefObject.cs b/src/libraries/System.Private.CoreLib/src/System/MarshalByRefObject.cs index 042617e4ba08c2..4bd0b21d93d2c2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MarshalByRefObject.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MarshalByRefObject.cs @@ -27,7 +27,7 @@ public virtual object InitializeLifetimeService() protected MarshalByRefObject MemberwiseClone(bool cloneIdentity) { - MarshalByRefObject mbr = (MarshalByRefObject)base.MemberwiseClone(); + MarshalByRefObject mbr = (MarshalByRefObject)MemberwiseClone(); return mbr; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Marvin.OrdinalIgnoreCase.cs b/src/libraries/System.Private.CoreLib/src/System/Marvin.OrdinalIgnoreCase.cs index 1888a5f0c612a3..a9d793327e4f7a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Marvin.OrdinalIgnoreCase.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Marvin.OrdinalIgnoreCase.cs @@ -85,7 +85,7 @@ private static int ComputeHash32OrdinalIgnoreCaseSlow(ref char data, int count, char[]? borrowedArr = null; Span scratch = (uint)count <= 64 ? stackalloc char[64] : (borrowedArr = ArrayPool.Shared.Rent(count)); - int charsWritten = System.Globalization.Ordinal.ToUpperOrdinal(new ReadOnlySpan(ref data, count), scratch); + int charsWritten = Globalization.Ordinal.ToUpperOrdinal(new ReadOnlySpan(ref data, count), scratch); Debug.Assert(charsWritten == count); // invariant case conversion should involve simple folding; preserve code unit count // Slice the array to the size returned by ToUpperInvariant. diff --git a/src/libraries/System.Private.CoreLib/src/System/MemberAccessException.cs b/src/libraries/System.Private.CoreLib/src/System/MemberAccessException.cs index 3863bc505e8b01..9e4cbdf085cf35 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MemberAccessException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MemberAccessException.cs @@ -8,6 +8,7 @@ //////////////////////////////////////////////////////////////////////////////// using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System @@ -15,7 +16,7 @@ namespace System // The MemberAccessException is thrown when trying to access a class // member fails. [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class MemberAccessException : SystemException { // Creates a new MemberAccessException with its message string set to diff --git a/src/libraries/System.Private.CoreLib/src/System/Memory.cs b/src/libraries/System.Private.CoreLib/src/System/Memory.cs index 70133be278d9c5..25e9778d66b538 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Memory.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Memory.cs @@ -35,7 +35,7 @@ namespace System /// /// The target array. /// Returns default when is null. - /// Thrown when is covariant and array's type is not exactly T[]. + /// Thrown when is covariant and array's type is not exactly T[]. [MethodImpl(MethodImplOptions.AggressiveInlining)] public Memory(T[]? array) { @@ -80,8 +80,8 @@ internal Memory(T[]? array, int start) /// The index at which to begin the memory. /// The number of items in the memory. /// Returns default when is null. - /// Thrown when is covariant and array's type is not exactly T[]. - /// + /// 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 >Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -116,7 +116,7 @@ public Memory(T[]? array, int start, int length) /// /// The memory manager. /// The number of items in the memory. - /// + /// /// Thrown when the specified is negative. /// /// For internal infrastructure only @@ -140,7 +140,7 @@ internal Memory(MemoryManager manager, int length) /// The memory manager. /// The index at which to begin the memory. /// The number of items in the memory. - /// + /// /// Thrown when the specified or is negative. /// /// For internal infrastructure only @@ -221,7 +221,7 @@ public override string ToString() /// Forms a slice out of the given memory, beginning at 'start'. /// /// The index at which to begin this slice. - /// + /// /// Thrown when the specified index is not in range (<0 or >Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -241,7 +241,7 @@ public Memory Slice(int start) /// /// The index at which to begin this slice. /// The desired length for the slice (exclusive). - /// + /// /// Thrown when the specified or end index is not in range (<0 or >Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -357,7 +357,7 @@ public unsafe Span Span /// a temporary location before the destination is overwritten. /// /// The Memory to copy items into. - /// + /// /// Thrown when the destination is shorter than the source. /// public void CopyTo(Memory destination) => Span.CopyTo(destination.Span); @@ -377,7 +377,7 @@ public unsafe Span Span /// The GC will not move the memory until the returned /// is disposed, enabling taking and using the memory's address. /// - /// + /// /// An instance with nonprimitive (non-blittable) members cannot be pinned. /// public unsafe MemoryHandle Pin() diff --git a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.Globalization.cs b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.Globalization.cs index c30436ce4918fa..4039f244d77bd6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.Globalization.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.Globalization.cs @@ -191,7 +191,7 @@ ref MemoryMarshal.GetReference(value), /// The source span. /// The destination span which contains the transformed characters. /// An object that supplies culture-specific casing rules. - /// If is null, will be used. + /// If is null, will be used. /// The number of characters written into the destination span. If the destination is too small, returns -1. /// The source and destination buffers overlap. public static int ToLower(this ReadOnlySpan source, Span destination, CultureInfo? culture) @@ -243,7 +243,7 @@ public static int ToLowerInvariant(this ReadOnlySpan source, Span de /// The source span. /// The destination span which contains the transformed characters. /// An object that supplies culture-specific casing rules. - /// If is null, will be used. + /// If is null, will be used. /// The number of characters written into the destination span. If the destination is too small, returns -1. /// The source and destination buffers overlap. public static int ToUpper(this ReadOnlySpan source, Span destination, CultureInfo? culture) diff --git a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs index 986644c4951aa0..681f0dc52e775c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MemoryExtensions.cs @@ -108,7 +108,7 @@ public static ReadOnlySpan AsSpan(this string? text) /// /// The target string. /// The index at which to begin this slice. - /// + /// /// Thrown when the specified index is not in range (<0 or >text.Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -186,7 +186,7 @@ public static ReadOnlySpan AsSpan(this string? text, Range range) /// The index at which to begin this slice. /// The desired length for the slice (exclusive). /// Returns default when is null. - /// + /// /// Thrown when the specified index or is not in range. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -226,7 +226,7 @@ public static ReadOnlyMemory AsMemory(this string? text) /// The target string. /// The index at which to begin this slice. /// Returns default when is null. - /// + /// /// Thrown when the specified index is not in range (<0 or >text.Length). /// public static ReadOnlyMemory AsMemory(this string? text, int start) @@ -269,7 +269,7 @@ public static ReadOnlyMemory AsMemory(this string? text, Index startIndex) /// The index at which to begin this slice. /// The desired length for the slice (exclusive). /// Returns default when is null. - /// + /// /// Thrown when the specified index or is not in range. /// public static ReadOnlyMemory AsMemory(this string? text, int start, int length) @@ -507,7 +507,7 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), } } - return SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), value, span.Length); + return SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), value, span.Length); } /// @@ -538,7 +538,7 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(value)), } } - return SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length); + return SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length); } /// Searches for the first index of any value other than the specified . @@ -1572,7 +1572,7 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(span)), } } - return SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), value, span.Length); + return SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), value, span.Length); } /// @@ -1603,7 +1603,7 @@ ref Unsafe.As(ref MemoryMarshal.GetReference(value)), } } - return SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length); + return SpanHelpers.LastIndexOf(ref MemoryMarshal.GetReference(span), span.Length, ref MemoryMarshal.GetReference(value), value.Length); } /// @@ -2383,8 +2383,8 @@ public static Span AsSpan(this T[]? array) /// The index at which to begin the Span. /// The number of items in the Span. /// Returns default when is null. - /// Thrown when is covariant and array's type is not exactly T[]. - /// + /// 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 >Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -2409,8 +2409,8 @@ public static Span AsSpan(this ArraySegment segment) /// The target array. /// The index at which to begin the Span. /// Returns default when is null. - /// Thrown when is covariant and array's type is not exactly T[]. - /// + /// 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 >segment.Count). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -2443,8 +2443,8 @@ public static Span AsSpan(this ArraySegment segment, Index startIndex) /// The index at which to begin the Span. /// The number of items in the Span. /// Returns default when is null. - /// Thrown when is covariant and array's type is not exactly T[]. - /// + /// 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 >segment.Count). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -2482,8 +2482,8 @@ public static Span AsSpan(this ArraySegment segment, Range range) /// The target array. /// The index at which to begin the memory. /// Returns default when is null. - /// Thrown when is covariant and array's type is not exactly T[]. - /// + /// 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 >array.Length). /// public static Memory AsMemory(this T[]? array, int start) => new Memory(array, start); @@ -2514,8 +2514,8 @@ public static Memory AsMemory(this T[]? array, Index startIndex) /// The index at which to begin the memory. /// The number of items in the memory. /// Returns default when is null. - /// Thrown when is covariant and array's type is not exactly T[]. - /// + /// 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 >Length). /// public static Memory AsMemory(this T[]? array, int start, int length) => new Memory(array, start, length); @@ -2552,8 +2552,8 @@ public static Memory AsMemory(this T[]? array, Range range) /// The target array. /// The index at which to begin the memory. /// Returns default when is null. - /// Thrown when is covariant and array's type is not exactly T[]. - /// + /// 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 >segment.Count). /// public static Memory AsMemory(this ArraySegment segment, int start) @@ -2572,8 +2572,8 @@ public static Memory AsMemory(this ArraySegment segment, int start) /// The index at which to begin the memory. /// The number of items in the memory. /// Returns default when is null. - /// Thrown when is covariant and array's type is not exactly T[]. - /// + /// 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 >segment.Count). /// public static Memory AsMemory(this ArraySegment segment, int start, int length) @@ -2593,7 +2593,7 @@ public static Memory AsMemory(this ArraySegment segment, int start, int /// ///The array to copy items from. /// The span to copy items into. - /// + /// /// Thrown when the destination Span is shorter than the source array. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -2609,7 +2609,7 @@ public static void CopyTo(this T[]? source, Span destination) /// ///The array to copy items from. /// The memory to copy items into. - /// + /// /// Thrown when the destination is shorter than the source array. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -2826,7 +2826,7 @@ ref MemoryMarshal.GetReference(span), /// of the index of the next element that is larger than or, if there is /// no larger element, the bitwise complement of . /// - /// + /// /// is . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -2850,7 +2850,7 @@ public static int BinarySearch( /// of the index of the next element that is larger than or, if there is /// no larger element, the bitwise complement of . /// - /// + /// /// is . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -2876,7 +2876,7 @@ public static int BinarySearch( /// of the index of the next element that is larger than or, if there is /// no larger element, the bitwise complement of . /// - /// + /// /// is . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -2900,7 +2900,7 @@ public static int BinarySearch( /// of the index of the next element that is larger than or, if there is /// no larger element, the bitwise complement of . /// - /// + /// /// is . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -2924,7 +2924,7 @@ public static int BinarySearch( /// of the index of the next element that is larger than or, if there is /// no larger element, the bitwise complement of . /// - /// + /// /// is . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -2950,7 +2950,7 @@ public static int BinarySearch( /// of the index of the next element that is larger than or, if there is /// no larger element, the bitwise complement of . /// - /// + /// /// is . /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/libraries/System.Private.CoreLib/src/System/MethodAccessException.cs b/src/libraries/System.Private.CoreLib/src/System/MethodAccessException.cs index ff7f21820a55ee..c31ddf1f5c5e2e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MethodAccessException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MethodAccessException.cs @@ -9,12 +9,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class MethodAccessException : MemberAccessException { public MethodAccessException() diff --git a/src/libraries/System.Private.CoreLib/src/System/MissingFieldException.cs b/src/libraries/System.Private.CoreLib/src/System/MissingFieldException.cs index 2c388e8d7fbae0..7d64f0f11aa479 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MissingFieldException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MissingFieldException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class MissingFieldException : MissingMemberException, ISerializable { public MissingFieldException() diff --git a/src/libraries/System.Private.CoreLib/src/System/MissingMemberException.cs b/src/libraries/System.Private.CoreLib/src/System/MissingMemberException.cs index 0ae639e0a31398..4fb2cb230d64ce 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MissingMemberException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MissingMemberException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public partial class MissingMemberException : MemberAccessException { public MissingMemberException() diff --git a/src/libraries/System.Private.CoreLib/src/System/MissingMethodException.cs b/src/libraries/System.Private.CoreLib/src/System/MissingMethodException.cs index e16db06b7ecf08..857b171975901f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MissingMethodException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MissingMethodException.cs @@ -11,12 +11,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class MissingMethodException : MissingMemberException { public MissingMethodException() diff --git a/src/libraries/System.Private.CoreLib/src/System/MulticastNotSupportedException.cs b/src/libraries/System.Private.CoreLib/src/System/MulticastNotSupportedException.cs index 0826497e1dd0d9..6f022c61305e7a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/MulticastNotSupportedException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/MulticastNotSupportedException.cs @@ -6,12 +6,13 @@ // This is thrown when you add multiple callbacks to a non-multicast delegate. //////////////////////////////////////////////////////////////////////////////// +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class MulticastNotSupportedException : SystemException { public MulticastNotSupportedException() diff --git a/src/libraries/System.Private.CoreLib/src/System/NotFiniteNumberException.cs b/src/libraries/System.Private.CoreLib/src/System/NotFiniteNumberException.cs index 021e3cf3a2c3e2..88fe578c51dc0a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/NotFiniteNumberException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/NotFiniteNumberException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class NotFiniteNumberException : ArithmeticException { private readonly double _offendingNumber; diff --git a/src/libraries/System.Private.CoreLib/src/System/NotImplementedException.cs b/src/libraries/System.Private.CoreLib/src/System/NotImplementedException.cs index 5afbddf0cacd83..bfc1c0d983eb9c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/NotImplementedException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/NotImplementedException.cs @@ -12,12 +12,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class NotImplementedException : SystemException { public NotImplementedException() diff --git a/src/libraries/System.Private.CoreLib/src/System/NotSupportedException.cs b/src/libraries/System.Private.CoreLib/src/System/NotSupportedException.cs index b5946a1611e356..2b4a34461f7625 100644 --- a/src/libraries/System.Private.CoreLib/src/System/NotSupportedException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/NotSupportedException.cs @@ -11,12 +11,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class NotSupportedException : SystemException { public NotSupportedException() diff --git a/src/libraries/System.Private.CoreLib/src/System/NullReferenceException.cs b/src/libraries/System.Private.CoreLib/src/System/NullReferenceException.cs index b54b391f2a2d44..5d466a6e0ae9bd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/NullReferenceException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/NullReferenceException.cs @@ -11,12 +11,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class NullReferenceException : SystemException { public NullReferenceException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Nullable.cs b/src/libraries/System.Private.CoreLib/src/System/Nullable.cs index a7d6954086c523..0766eca30a4dff 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Nullable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Nullable.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Runtime.CompilerServices; using System.Runtime.Versioning; #pragma warning disable CA1066 // Implement IEquatable when overriding Object.Equals @@ -16,7 +17,7 @@ namespace System [Serializable] [NonVersionable] // This only applies to field layout - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public partial struct Nullable where T : struct { private readonly bool hasValue; // Do not rename (binary serialization) @@ -66,16 +67,16 @@ public override bool Equals(object? other) public override string? ToString() => hasValue ? value.ToString() : ""; [NonVersionable] - public static implicit operator Nullable(T value) => - new Nullable(value); + public static implicit operator T?(T value) => + new T?(value); [NonVersionable] - public static explicit operator T(Nullable value) => value!.Value; + public static explicit operator T(T? value) => value!.Value; } public static class Nullable { - public static int Compare(Nullable n1, Nullable n2) where T : struct + public static int Compare(T? n1, T? n2) where T : struct { if (n1.HasValue) { @@ -86,7 +87,7 @@ public static int Compare(Nullable n1, Nullable n2) where T : struct return 0; } - public static bool Equals(Nullable n1, Nullable n2) where T : struct + public static bool Equals(T? n1, T? n2) where T : struct { if (n1.HasValue) { @@ -107,7 +108,7 @@ public static bool Equals(Nullable n1, Nullable n2) where T : struct { // Instantiated generic type only Type genericType = nullableType.GetGenericTypeDefinition(); - if (object.ReferenceEquals(genericType, typeof(Nullable<>))) + if (ReferenceEquals(genericType, typeof(Nullable<>))) { return nullableType.GetGenericArguments()[0]; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs index b032906f903fbb..6df1d1957f901e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs @@ -945,13 +945,17 @@ internal static uint ResetLowestSetBit(uint value) } /// - /// Reset specific bit in the given value + /// Flip the bit at a specific position in a given value. + /// Similar in behavior to the x86 instruction BTC (Bit Test and Complement). /// + /// The value. + /// The zero-based index of the bit to flip. + /// Any value outside the range [0..31] is treated as congruent mod 32. + /// The new value. [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static uint ResetBit(uint value, int bitPos) + internal static uint FlipBit(uint value, int index) { - // TODO: Recognize BTR on x86 and LSL+BIC on ARM - return value & ~(uint)(1 << bitPos); + return value ^ (1u << index); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix3x2.cs b/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix3x2.cs index 49dac972571e7b..bc7fa66d7f7880 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix3x2.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Numerics/Matrix3x2.cs @@ -110,7 +110,7 @@ public Vector2 Translation /// The first matrix. /// The second matrix. /// The matrix that contains the summed values. - /// The method defines the operation of the addition operator for objects. + /// The method defines the operation of the addition operator for objects. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Matrix3x2 operator +(Matrix3x2 value1, Matrix3x2 value2) => (value1.AsImpl() + value2.AsImpl()).AsM3x2(); @@ -136,7 +136,7 @@ public Vector2 Translation /// The first matrix. /// The second matrix. /// The product matrix. - /// The method defines the operation of the multiplication operator for objects. + /// The method defines the operation of the multiplication operator for objects. public static Matrix3x2 operator *(Matrix3x2 value1, Matrix3x2 value2) => (value1.AsImpl() * value2.AsImpl()).AsM3x2(); @@ -144,7 +144,7 @@ public Vector2 Translation /// The matrix to scale. /// The scaling value to use. /// The scaled matrix. - /// The method defines the operation of the multiplication operator for objects. + /// The method defines the operation of the multiplication operator for objects. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Matrix3x2 operator *(Matrix3x2 value1, float value2) => (value1.AsImpl() * value2).AsM3x2(); @@ -153,7 +153,7 @@ public Vector2 Translation /// The first matrix. /// The second matrix. /// The matrix containing the values that result from subtracting each element in from its corresponding element in . - /// The method defines the operation of the subtraction operator for objects. + /// The method defines the operation of the subtraction operator for objects. [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Matrix3x2 operator -(Matrix3x2 value1, Matrix3x2 value2) => (value1.AsImpl() - value2.AsImpl()).AsM3x2(); @@ -161,7 +161,7 @@ public Vector2 Translation /// Negates the specified matrix by multiplying all its values by -1. /// The matrix to negate. /// The negated matrix. - /// + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Matrix3x2 operator -(Matrix3x2 value) => (-value.AsImpl()).AsM3x2(); @@ -309,7 +309,7 @@ public static Matrix3x2 Subtract(Matrix3x2 value1, Matrix3x2 value2) /// Returns a value that indicates whether this instance and a specified object are equal. /// The object to compare with the current instance. /// if the current instance and are equal; otherwise, . If is , the method returns . - /// The current instance and are equal if is a object and the corresponding elements of each matrix are equal. + /// The current instance and are equal if is a object and the corresponding elements of each matrix are equal. [MethodImpl(MethodImplOptions.AggressiveInlining)] public override readonly bool Equals([NotNullWhen(true)] object? obj) => AsROImpl().Equals(obj); diff --git a/src/libraries/System.Private.CoreLib/src/System/OperationCanceledException.cs b/src/libraries/System.Private.CoreLib/src/System/OperationCanceledException.cs index e0e0c72754aedc..7a88cf737fcb5b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/OperationCanceledException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/OperationCanceledException.cs @@ -11,13 +11,14 @@ ===========================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Threading; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class OperationCanceledException : SystemException { [NonSerialized] diff --git a/src/libraries/System.Private.CoreLib/src/System/OutOfMemoryException.cs b/src/libraries/System.Private.CoreLib/src/System/OutOfMemoryException.cs index 4094711a82f8e0..f6f6430ec05294 100644 --- a/src/libraries/System.Private.CoreLib/src/System/OutOfMemoryException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/OutOfMemoryException.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System @@ -10,7 +11,7 @@ namespace System /// The exception class for OOM. /// [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class OutOfMemoryException : SystemException { public OutOfMemoryException() : base( diff --git a/src/libraries/System.Private.CoreLib/src/System/OverflowException.cs b/src/libraries/System.Private.CoreLib/src/System/OverflowException.cs index 8d30c3b75c299a..8899e06d78a831 100644 --- a/src/libraries/System.Private.CoreLib/src/System/OverflowException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/OverflowException.cs @@ -11,12 +11,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class OverflowException : ArithmeticException { public OverflowException() diff --git a/src/libraries/System.Private.CoreLib/src/System/PlatformNotSupportedException.cs b/src/libraries/System.Private.CoreLib/src/System/PlatformNotSupportedException.cs index 474e0736f638ee..0dc21edd1a727e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/PlatformNotSupportedException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/PlatformNotSupportedException.cs @@ -11,12 +11,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class PlatformNotSupportedException : NotSupportedException { public PlatformNotSupportedException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Progress.cs b/src/libraries/System.Private.CoreLib/src/System/Progress.cs index 237c8841adbd82..2e17ec0745c140 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Progress.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Progress.cs @@ -13,7 +13,7 @@ namespace System /// /// Any handler provided to the constructor or event handlers registered with /// the event are invoked through a - /// instance captured + /// instance captured /// when the instance is constructed. If there is no current SynchronizationContext /// at the time of construction, the callbacks will be invoked on the ThreadPool. /// @@ -40,11 +40,11 @@ public Progress() /// /// A handler to invoke for each reported progress value. This handler will be invoked /// in addition to any delegates registered with the event. - /// Depending on the instance captured by + /// Depending on the instance captured by /// the at construction, it's possible that this handler instance /// could be invoked concurrently with itself. /// - /// The is null (Nothing in Visual Basic). + /// The is null (Nothing in Visual Basic). public Progress(Action handler) : this() { ArgumentNullException.ThrowIfNull(handler); @@ -55,7 +55,7 @@ public Progress(Action handler) : this() /// Raised for each reported progress value. /// /// Handlers registered with this event will be invoked on the - /// captured when the instance was constructed. + /// captured when the instance was constructed. /// public event EventHandler? ProgressChanged; diff --git a/src/libraries/System.Private.CoreLib/src/System/Random.ImplBase.cs b/src/libraries/System.Private.CoreLib/src/System/Random.ImplBase.cs index 6bd1b8a1ac943b..c7857b156262df 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Random.ImplBase.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Random.ImplBase.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.Runtime.CompilerServices; namespace System @@ -57,8 +58,7 @@ internal static uint NextUInt32(uint maxValue, XoshiroImpl xoshiro) [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static ulong NextUInt64(ulong maxValue, XoshiroImpl xoshiro) { - UInt128 randomProduct = (UInt128)maxValue * xoshiro.NextUInt64(); - ulong lowPart = (ulong)randomProduct; + ulong randomProduct = Math.BigMul(maxValue, xoshiro.NextUInt64(), out ulong lowPart); if (lowPart < maxValue) { @@ -66,12 +66,11 @@ internal static ulong NextUInt64(ulong maxValue, XoshiroImpl xoshiro) while (lowPart < remainder) { - randomProduct = (UInt128)maxValue * xoshiro.NextUInt64(); - lowPart = (ulong)randomProduct; + randomProduct = Math.BigMul(maxValue, xoshiro.NextUInt64(), out lowPart); } } - return (ulong)(randomProduct >> 64); + return randomProduct; } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/RankException.cs b/src/libraries/System.Private.CoreLib/src/System/RankException.cs index 4bfe6529ee32e3..be49c02b0fee8a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/RankException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/RankException.cs @@ -12,12 +12,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class RankException : SystemException { public RankException() diff --git a/src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs b/src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs index 277eb9e5f1e8fe..9037e4110817e1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs @@ -37,7 +37,7 @@ namespace System /// /// The target array. /// Returns default when is null. - /// Thrown when is covariant and array's type is not exactly T[]. + /// Thrown when is covariant and array's type is not exactly T[]. [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyMemory(T[]? array) { @@ -60,8 +60,8 @@ public ReadOnlyMemory(T[]? array) /// The index at which to begin the memory. /// The number of items in the memory. /// Returns default when is null. - /// Thrown when is covariant and array's type is not exactly T[]. - /// + /// 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 >Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -150,7 +150,7 @@ public override string ToString() /// Forms a slice out of the given memory, beginning at 'start'. /// /// The index at which to begin this slice. - /// + /// /// Thrown when the specified index is not in range (<0 or >Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -170,7 +170,7 @@ public ReadOnlyMemory Slice(int start) /// /// The index at which to begin this slice. /// The desired length for the slice (exclusive). - /// + /// /// Thrown when the specified or end index is not in range (<0 or >Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -279,7 +279,7 @@ public unsafe ReadOnlySpan Span /// a temporary location before the destination is overwritten. /// /// The Memory to copy items into. - /// + /// /// Thrown when the destination is shorter than the source. /// public void CopyTo(Memory destination) => Span.CopyTo(destination.Span); @@ -299,7 +299,7 @@ public unsafe ReadOnlySpan Span /// The GC will not move the memory until the returned /// is disposed, enabling taking and using the memory's address. /// - /// + /// /// An instance with nonprimitive (non-blittable) members cannot be pinned. /// public unsafe MemoryHandle Pin() diff --git a/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs b/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs index ad691aedd10655..fecdfe7db790f9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ReadOnlySpan.cs @@ -57,7 +57,7 @@ public ReadOnlySpan(T[]? array) /// The index at which to begin the read-only span. /// The number of items in the read-only span. /// Returns default when is null. - /// + /// /// Thrown when the specified or end index is not in the range (<0 or >Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -91,10 +91,10 @@ public ReadOnlySpan(T[]? array, int start, int length) /// /// An unmanaged pointer to memory. /// The number of elements the memory contains. - /// + /// /// Thrown when is reference type or contains pointers and hence cannot be stored in unmanaged memory. /// - /// + /// /// Thrown when the specified is negative. /// [CLSCompliant(false)] @@ -136,7 +136,7 @@ internal ReadOnlySpan(ref T reference, int length) /// /// /// - /// + /// /// Thrown when index less than 0 or index greater than or equal to Length /// public ref readonly T this[int index] @@ -181,7 +181,7 @@ public bool IsEmpty /// /// This method is not supported as spans cannot be boxed. To compare two spans, use operator==. /// - /// + /// /// Always thrown by this method. /// [Obsolete("Equals() on ReadOnlySpan will always throw an exception. Use the equality operator instead.")] @@ -192,7 +192,7 @@ public override bool Equals(object? obj) => /// /// This method is not supported as spans cannot be boxed. /// - /// + /// /// Always thrown by this method. /// [Obsolete("GetHashCode() on ReadOnlySpan will always throw an exception.")] @@ -277,7 +277,7 @@ public ref readonly T GetPinnableReference() /// a temporary location before the destination is overwritten. /// /// The span to copy items into. - /// + /// /// Thrown when the destination Span is shorter than the source Span. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -322,7 +322,7 @@ public bool TryCopyTo(Span destination) /// public static bool operator ==(ReadOnlySpan left, ReadOnlySpan right) => left._length == right._length && - Unsafe.AreSame(ref left._reference, ref right._reference); + Unsafe.AreSame(ref left._reference, ref right._reference); /// /// For , returns a new instance of string that represents the characters pointed to by the span. @@ -341,7 +341,7 @@ public override string ToString() /// Forms a slice out of the given read-only span, beginning at 'start'. /// /// The index at which to begin this slice. - /// + /// /// Thrown when the specified index is not in range (<0 or >Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -358,7 +358,7 @@ public ReadOnlySpan Slice(int start) /// /// The index at which to begin this slice. /// The desired length for the slice (exclusive). - /// + /// /// Thrown when the specified or end index is not in range (<0 or >Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/AmbiguousMatchException.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/AmbiguousMatchException.cs index e86467d58a2330..6e75c436efa3a3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/AmbiguousMatchException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/AmbiguousMatchException.cs @@ -1,16 +1,17 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Reflection { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class AmbiguousMatchException : SystemException { public AmbiguousMatchException() - : base(SR.Arg_AmbiguousMatchException) + : base(SR.Arg_AmbiguousMatchException_NoMessage) { HResult = HResults.COR_E_AMBIGUOUSMATCH; } 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 ea22b60e5544e7..15e753aaee3792 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Assembly.cs @@ -333,7 +333,7 @@ public static Assembly LoadFile(string path) try { // Load the dependency via LoadFrom so that it goes through the same path of being in the LoadFrom list. - return Assembly.LoadFrom(requestedAssemblyPath); + return LoadFrom(requestedAssemblyPath); } catch (FileNotFoundException) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs index 791f6f22d9f9f7..7440e1fae8dacd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/AssemblyName.cs @@ -298,7 +298,7 @@ public void OnDeserialization(object? sender) /// public static bool ReferenceMatchesDefinition(AssemblyName? reference, AssemblyName? definition) { - if (object.ReferenceEquals(reference, definition)) + if (ReferenceEquals(reference, definition)) return true; ArgumentNullException.ThrowIfNull(reference); ArgumentNullException.ThrowIfNull(definition); diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeFormatException.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeFormatException.cs index f381af37df05cc..b70a1c471b7100 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeFormatException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/CustomAttributeFormatException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Reflection { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class CustomAttributeFormatException : FormatException { public CustomAttributeFormatException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs index 2ce19ba7a7546b..4989a83cc49124 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/AssemblyBuilder.cs @@ -48,7 +48,7 @@ public void SetCustomAttribute(CustomAttributeBuilder customBuilder) SetCustomAttributeCore(customBuilder.Ctor, customBuilder.Data); } - [System.ObsoleteAttribute("Assembly.CodeBase and Assembly.EscapedCodeBase are only included for .NET Framework compatibility. Use Assembly.Location instead.", DiagnosticId = "SYSLIB0012", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] + [Obsolete("Assembly.CodeBase and Assembly.EscapedCodeBase are only included for .NET Framework compatibility. Use Assembly.Location instead.", DiagnosticId = "SYSLIB0012", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] [RequiresAssemblyFiles(ThrowingMessageInRAF)] public override string? CodeBase => throw new NotSupportedException(SR.NotSupported_DynamicAssembly); public override string Location => string.Empty; diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/FieldOnTypeBuilderInstantiation.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/FieldOnTypeBuilderInstantiation.cs index bd851d3cf6dc12..1aadda2346a012 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/FieldOnTypeBuilderInstantiation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/FieldOnTypeBuilderInstantiation.cs @@ -45,7 +45,7 @@ internal FieldOnTypeBuilderInstantiation(FieldInfo field, TypeBuilderInstantiati internal FieldInfo FieldInfo => _field; #region MemberInfo Overrides - public override MemberTypes MemberType => System.Reflection.MemberTypes.Field; + public override MemberTypes MemberType => MemberTypes.Field; public override string Name => _field.Name; public override Type? DeclaringType => _type; public override Type? ReflectedType => _type; 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 84ae8bbb54c113..f277a897457ddf 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 @@ -126,7 +126,7 @@ public virtual void EmitWriteLine(LocalBuilder localBuilder) throw new ArgumentException(SR.NotSupported_OutputStreamUsingTypeBuilder); } parameterTypes[0] = cls; - MethodInfo? mi = typeof(System.IO.TextWriter).GetMethod("WriteLine", parameterTypes); + MethodInfo? mi = typeof(IO.TextWriter).GetMethod("WriteLine", parameterTypes); if (mi == null) { throw new ArgumentException(SR.Argument_EmitWriteLineType, nameof(localBuilder)); @@ -163,7 +163,7 @@ public virtual void EmitWriteLine(FieldInfo fld) throw new NotSupportedException(SR.NotSupported_OutputStreamUsingTypeBuilder); } parameterTypes[0] = cls; - MethodInfo? mi = typeof(System.IO.TextWriter).GetMethod("WriteLine", parameterTypes); + MethodInfo? mi = typeof(IO.TextWriter).GetMethod("WriteLine", parameterTypes); if (mi == null) { throw new ArgumentException(SR.Argument_EmitWriteLineType, nameof(fld)); diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/Opcode.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/Opcode.cs index d37f9765c87461..e9fdc1ec38c9ad 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/Opcode.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/Opcode.cs @@ -103,7 +103,7 @@ public string? Name return name; // Create ilasm style name from the enum value name. - name = Enum.GetName(opCodeValue)!.ToLowerInvariant().Replace('_', '.'); + name = Enum.GetName(opCodeValue)!.ToLowerInvariant().Replace('_', '.'); Volatile.Write(ref nameCache[idx], name); return name; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/SymbolType.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/SymbolType.cs index 89834220d47a26..8d3f6e76caf0f9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/SymbolType.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Emit/SymbolType.cs @@ -350,7 +350,7 @@ public override string ToString() public override string? Namespace => _baseType.Namespace; - public override Type BaseType => typeof(System.Array); + public override Type BaseType => typeof(Array); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] protected override ConstructorInfo GetConstructorImpl(BindingFlags bindingAttr, Binder? binder, diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/IReflect.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/IReflect.cs index 6eed135d1f6863..40b5fde66e1753 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/IReflect.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/IReflect.cs @@ -49,11 +49,11 @@ public interface IReflect PropertyInfo[] GetProperties(BindingFlags bindingAttr); // Return an array of members which match the passed in name. - [DynamicallyAccessedMembers(System.Type.GetAllMembers)] + [DynamicallyAccessedMembers(Type.GetAllMembers)] MemberInfo[] GetMember(string name, BindingFlags bindingAttr); // Return an array of all of the members defined for this object. - [DynamicallyAccessedMembers(System.Type.GetAllMembers)] + [DynamicallyAccessedMembers(Type.GetAllMembers)] MemberInfo[] GetMembers(BindingFlags bindingAttr); // Description of the Binding Process. diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/InvalidFilterCriteriaException.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/InvalidFilterCriteriaException.cs index 14a84fe6baade9..5efdf3ee6f2d14 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/InvalidFilterCriteriaException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/InvalidFilterCriteriaException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Reflection { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class InvalidFilterCriteriaException : ApplicationException { public InvalidFilterCriteriaException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/InvokerEmitUtil.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/InvokerEmitUtil.cs index c800f9e3ef02c0..0dac01f77a0e42 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/InvokerEmitUtil.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/InvokerEmitUtil.cs @@ -197,7 +197,7 @@ public static MethodInfo DisableInline() => #else private static MethodInfo? s_NextCallReturnAddress; public static MethodInfo NextCallReturnAddress() => - s_NextCallReturnAddress ??= typeof(System.StubHelpers.StubHelpers).GetMethod(nameof(System.StubHelpers.StubHelpers.NextCallReturnAddress), BindingFlags.NonPublic | BindingFlags.Static)!; + s_NextCallReturnAddress ??= typeof(StubHelpers.StubHelpers).GetMethod(nameof(StubHelpers.StubHelpers.NextCallReturnAddress), BindingFlags.NonPublic | BindingFlags.Static)!; #endif } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/Module.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/Module.cs index 8234c96676d6f9..ef3140287e3d60 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/Module.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/Module.cs @@ -40,11 +40,11 @@ protected Module() { } { ArgumentNullException.ThrowIfNull(name); - return GetMethodImpl(name, Module.DefaultLookup, null, CallingConventions.Any, null, null); + return GetMethodImpl(name, DefaultLookup, null, CallingConventions.Any, null, null); } [RequiresUnreferencedCode("Methods might be removed")] - public MethodInfo? GetMethod(string name, Type[] types) => GetMethod(name, Module.DefaultLookup, null, CallingConventions.Any, types, null); + public MethodInfo? GetMethod(string name, Type[] types) => GetMethod(name, DefaultLookup, null, CallingConventions.Any, types, null); [RequiresUnreferencedCode("Methods might be removed")] public MethodInfo? GetMethod(string name, BindingFlags bindingAttr, Binder? binder, CallingConventions callConvention, Type[] types, ParameterModifier[]? modifiers) { @@ -62,17 +62,17 @@ protected Module() { } protected virtual MethodInfo? GetMethodImpl(string name, BindingFlags bindingAttr, Binder? binder, CallingConventions callConvention, Type[]? types, ParameterModifier[]? modifiers) { throw NotImplemented.ByDesign; } [RequiresUnreferencedCode("Methods might be removed")] - public MethodInfo[] GetMethods() => GetMethods(Module.DefaultLookup); + public MethodInfo[] GetMethods() => GetMethods(DefaultLookup); [RequiresUnreferencedCode("Methods might be removed")] public virtual MethodInfo[] GetMethods(BindingFlags bindingFlags) { throw NotImplemented.ByDesign; } [RequiresUnreferencedCode("Fields might be removed")] - public FieldInfo? GetField(string name) => GetField(name, Module.DefaultLookup); + public FieldInfo? GetField(string name) => GetField(name, DefaultLookup); [RequiresUnreferencedCode("Fields might be removed")] public virtual FieldInfo? GetField(string name, BindingFlags bindingAttr) { throw NotImplemented.ByDesign; } [RequiresUnreferencedCode("Fields might be removed")] - public FieldInfo[] GetFields() => GetFields(Module.DefaultLookup); + public FieldInfo[] GetFields() => GetFields(DefaultLookup); [RequiresUnreferencedCode("Fields might be removed")] public virtual FieldInfo[] GetFields(BindingFlags bindingFlags) { throw NotImplemented.ByDesign; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/SignatureGenericParameterType.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/SignatureGenericParameterType.cs index 58662a655a49ed..447f40eb917df3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/SignatureGenericParameterType.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/SignatureGenericParameterType.cs @@ -30,8 +30,8 @@ protected SignatureGenericParameterType(int position) internal sealed override SignatureType? ElementType => null; public sealed override int GetArrayRank() => throw new ArgumentException(SR.Argument_HasToBeArrayClass); public sealed override Type GetGenericTypeDefinition() => throw new InvalidOperationException(SR.InvalidOperation_NotGenericType); - public sealed override Type[] GetGenericArguments() => Type.EmptyTypes; - public sealed override Type[] GenericTypeArguments => Type.EmptyTypes; + public sealed override Type[] GetGenericArguments() => EmptyTypes; + public sealed override Type[] GenericTypeArguments => EmptyTypes; public sealed override int GenericParameterPosition => _position; public abstract override string Name { get; } public sealed override string? Namespace => null; diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/SignatureHasElementType.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/SignatureHasElementType.cs index 4226d61270ad70..694087149ee479 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/SignatureHasElementType.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/SignatureHasElementType.cs @@ -31,8 +31,8 @@ protected SignatureHasElementType(SignatureType elementType) internal sealed override SignatureType? ElementType => _elementType; public abstract override int GetArrayRank(); public sealed override Type GetGenericTypeDefinition() => throw new InvalidOperationException(SR.InvalidOperation_NotGenericType); - public sealed override Type[] GetGenericArguments() => Type.EmptyTypes; - public sealed override Type[] GenericTypeArguments => Type.EmptyTypes; + public sealed override Type[] GetGenericArguments() => EmptyTypes; + public sealed override Type[] GenericTypeArguments => EmptyTypes; public sealed override int GenericParameterPosition => throw new InvalidOperationException(SR.Arg_NotGenericParameter); public sealed override string Name => _elementType.Name + Suffix; public sealed override string? Namespace => _elementType.Namespace; diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/TargetException.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/TargetException.cs index 9efa8c9a1bc159..14a84c129afe72 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/TargetException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/TargetException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Reflection { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class TargetException : ApplicationException { public TargetException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/TargetInvocationException.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/TargetInvocationException.cs index 82b8a2b0ba1116..04219ef4b90bb3 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/TargetInvocationException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/TargetInvocationException.cs @@ -1,12 +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.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Reflection { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class TargetInvocationException : ApplicationException { public TargetInvocationException(Exception? inner) diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/TargetParameterCountException.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/TargetParameterCountException.cs index de84822e6c92a9..be8841c7a7ed96 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/TargetParameterCountException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/TargetParameterCountException.cs @@ -1,12 +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.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Reflection { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class TargetParameterCountException : ApplicationException { public TargetParameterCountException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Reflection/TypeInfo.cs b/src/libraries/System.Private.CoreLib/src/System/Reflection/TypeInfo.cs index 7164e969db16b5..5b90e287c53b69 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Reflection/TypeInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Reflection/TypeInfo.cs @@ -13,22 +13,22 @@ protected TypeInfo() { } TypeInfo IReflectableType.GetTypeInfo() => this; public virtual Type AsType() => this; - public virtual Type[] GenericTypeParameters => IsGenericTypeDefinition ? GetGenericArguments() : Type.EmptyTypes; + public virtual Type[] GenericTypeParameters => IsGenericTypeDefinition ? GetGenericArguments() : EmptyTypes; [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)] - public virtual EventInfo? GetDeclaredEvent(string name) => GetEvent(name, TypeInfo.DeclaredOnlyLookup); + public virtual EventInfo? GetDeclaredEvent(string name) => GetEvent(name, DeclaredOnlyLookup); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] - public virtual FieldInfo? GetDeclaredField(string name) => GetField(name, TypeInfo.DeclaredOnlyLookup); + public virtual FieldInfo? GetDeclaredField(string name) => GetField(name, DeclaredOnlyLookup); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] - public virtual MethodInfo? GetDeclaredMethod(string name) => GetMethod(name, TypeInfo.DeclaredOnlyLookup); + public virtual MethodInfo? GetDeclaredMethod(string name) => GetMethod(name, DeclaredOnlyLookup); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] - public virtual TypeInfo? GetDeclaredNestedType(string name) => GetNestedType(name, TypeInfo.DeclaredOnlyLookup)?.GetTypeInfo(); + public virtual TypeInfo? GetDeclaredNestedType(string name) => GetNestedType(name, DeclaredOnlyLookup)?.GetTypeInfo(); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] - public virtual PropertyInfo? GetDeclaredProperty(string name) => GetProperty(name, TypeInfo.DeclaredOnlyLookup); + public virtual PropertyInfo? GetDeclaredProperty(string name) => GetProperty(name, DeclaredOnlyLookup); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] public virtual IEnumerable GetDeclaredMethods(string name) @@ -42,40 +42,40 @@ public virtual IEnumerable GetDeclaredMethods(string name) [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", Justification = "The yield return state machine doesn't propagate annotations")] static MethodInfo[] GetDeclaredOnlyMethods( - Type type) => type.GetMethods(TypeInfo.DeclaredOnlyLookup); + Type type) => type.GetMethods(DeclaredOnlyLookup); } public virtual IEnumerable DeclaredConstructors { [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] - get => GetConstructors(TypeInfo.DeclaredOnlyLookup); + get => GetConstructors(DeclaredOnlyLookup); } public virtual IEnumerable DeclaredEvents { [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)] - get => GetEvents(TypeInfo.DeclaredOnlyLookup); + get => GetEvents(DeclaredOnlyLookup); } public virtual IEnumerable DeclaredFields { [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] - get => GetFields(TypeInfo.DeclaredOnlyLookup); + get => GetFields(DeclaredOnlyLookup); } public virtual IEnumerable DeclaredMembers { [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] - get => GetMembers(TypeInfo.DeclaredOnlyLookup); + get => GetMembers(DeclaredOnlyLookup); } public virtual IEnumerable DeclaredMethods { [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] - get => GetMethods(TypeInfo.DeclaredOnlyLookup); + get => GetMethods(DeclaredOnlyLookup); } - public virtual IEnumerable DeclaredNestedTypes + public virtual IEnumerable DeclaredNestedTypes { [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] get @@ -88,14 +88,14 @@ public virtual IEnumerable DeclaredNestedTypes [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", Justification = "The yield return state machine doesn't propagate annotations")] static Type[] GetDeclaredOnlyNestedTypes( - Type type) => type.GetNestedTypes(TypeInfo.DeclaredOnlyLookup); + Type type) => type.GetNestedTypes(DeclaredOnlyLookup); } } public virtual IEnumerable DeclaredProperties { [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] - get => GetProperties(TypeInfo.DeclaredOnlyLookup); + get => GetProperties(DeclaredOnlyLookup); } public virtual IEnumerable ImplementedInterfaces diff --git a/src/libraries/System.Private.CoreLib/src/System/Resources/FastResourceComparer.cs b/src/libraries/System.Private.CoreLib/src/System/Resources/FastResourceComparer.cs index 4afac2aaab791f..00c0413db39706 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Resources/FastResourceComparer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Resources/FastResourceComparer.cs @@ -28,12 +28,12 @@ internal sealed class FastResourceComparer : IComparer, IEqualityComparer, IComp public int GetHashCode(object key) { string s = (string)key; - return FastResourceComparer.HashFunction(s); + return HashFunction(s); } public int GetHashCode([DisallowNull] string? key) { - return FastResourceComparer.HashFunction(key!); + return HashFunction(key!); } // This hash function MUST be publicly documented with the resource diff --git a/src/libraries/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs b/src/libraries/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs index 6a100e23251aff..6ba7d66c84fa6d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Resources/ManifestBasedResourceGroveler.cs @@ -162,7 +162,7 @@ internal static CultureInfo GetNeutralResourcesLanguage(Assembly a, out Ultimate // fires, please fix the build process for the BCL directory. if (a == typeof(object).Assembly) { - Debug.Fail(System.CoreLib.Name + "'s NeutralResourcesLanguageAttribute is a malformed culture name! name: \"" + attr.CultureName + "\" Exception: " + e); + Debug.Fail(CoreLib.Name + "'s NeutralResourcesLanguageAttribute is a malformed culture name! name: \"" + attr.CultureName + "\" Exception: " + e); return CultureInfo.InvariantCulture; } @@ -472,10 +472,10 @@ private void HandleResourceStreamMissing(string fileName) { Debug.Assert(_mediator.BaseName != null); // Keep people from bothering me about resources problems - if (_mediator.MainAssembly == typeof(object).Assembly && _mediator.BaseName.Equals(System.CoreLib.Name)) + if (_mediator.MainAssembly == typeof(object).Assembly && _mediator.BaseName.Equals(CoreLib.Name)) { // This would break CultureInfo & all our exceptions. - Debug.Fail("Couldn't get " + System.CoreLib.Name + ResourceManager.ResFileExtension + " from " + System.CoreLib.Name + "'s assembly" + Environment.NewLineConst + Environment.NewLineConst + "Are you building the runtime on your machine? Chances are the BCL directory didn't build correctly. Type 'build -c' in the BCL directory. If you get build errors, look at buildd.log. If you then can't figure out what's wrong (and you aren't changing the assembly-related metadata code), ask a BCL dev.\n\nIf you did NOT build the runtime, you shouldn't be seeing this and you've found a bug."); + Debug.Fail("Couldn't get " + CoreLib.Name + ResourceManager.ResFileExtension + " from " + CoreLib.Name + "'s assembly" + Environment.NewLineConst + Environment.NewLineConst + "Are you building the runtime on your machine? Chances are the BCL directory didn't build correctly. Type 'build -c' in the BCL directory. If you get build errors, look at buildd.log. If you then can't figure out what's wrong (and you aren't changing the assembly-related metadata code), ask a BCL dev.\n\nIf you did NOT build the runtime, you shouldn't be seeing this and you've found a bug."); // We cannot continue further - simply FailFast. const string MesgFailFast = System.CoreLib.Name + ResourceManager.ResFileExtension + " couldn't be found! Large parts of the BCL won't work!"; diff --git a/src/libraries/System.Private.CoreLib/src/System/Resources/MissingManifestResourceException.cs b/src/libraries/System.Private.CoreLib/src/System/Resources/MissingManifestResourceException.cs index cfce9985321dd2..05c204d2d04b99 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Resources/MissingManifestResourceException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Resources/MissingManifestResourceException.cs @@ -2,31 +2,32 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Resources { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] [EditorBrowsable(EditorBrowsableState.Never)] public class MissingManifestResourceException : SystemException { public MissingManifestResourceException() : base(SR.Arg_MissingManifestResourceException) { - HResult = System.HResults.COR_E_MISSINGMANIFESTRESOURCE; + HResult = HResults.COR_E_MISSINGMANIFESTRESOURCE; } public MissingManifestResourceException(string? message) : base(message) { - HResult = System.HResults.COR_E_MISSINGMANIFESTRESOURCE; + HResult = HResults.COR_E_MISSINGMANIFESTRESOURCE; } public MissingManifestResourceException(string? message, Exception? inner) : base(message, inner) { - HResult = System.HResults.COR_E_MISSINGMANIFESTRESOURCE; + HResult = HResults.COR_E_MISSINGMANIFESTRESOURCE; } [Obsolete(Obsoletions.LegacyFormatterImplMessage, DiagnosticId = Obsoletions.LegacyFormatterImplDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] diff --git a/src/libraries/System.Private.CoreLib/src/System/Resources/MissingSatelliteAssemblyException.cs b/src/libraries/System.Private.CoreLib/src/System/Resources/MissingSatelliteAssemblyException.cs index de7724b91dcead..f71a243c40af78 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Resources/MissingSatelliteAssemblyException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Resources/MissingSatelliteAssemblyException.cs @@ -15,12 +15,13 @@ ===========================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Resources { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class MissingSatelliteAssemblyException : SystemException { private readonly string? _cultureName; @@ -28,26 +29,26 @@ public class MissingSatelliteAssemblyException : SystemException public MissingSatelliteAssemblyException() : base(SR.MissingSatelliteAssembly_Default) { - HResult = System.HResults.COR_E_MISSINGSATELLITEASSEMBLY; + HResult = HResults.COR_E_MISSINGSATELLITEASSEMBLY; } public MissingSatelliteAssemblyException(string? message) : base(message) { - HResult = System.HResults.COR_E_MISSINGSATELLITEASSEMBLY; + HResult = HResults.COR_E_MISSINGSATELLITEASSEMBLY; } public MissingSatelliteAssemblyException(string? message, string? cultureName) : base(message) { - HResult = System.HResults.COR_E_MISSINGSATELLITEASSEMBLY; + HResult = HResults.COR_E_MISSINGSATELLITEASSEMBLY; _cultureName = cultureName; } public MissingSatelliteAssemblyException(string? message, Exception? inner) : base(message, inner) { - HResult = System.HResults.COR_E_MISSINGSATELLITEASSEMBLY; + HResult = HResults.COR_E_MISSINGSATELLITEASSEMBLY; } [Obsolete(Obsoletions.LegacyFormatterImplMessage, DiagnosticId = Obsoletions.LegacyFormatterImplDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] diff --git a/src/libraries/System.Private.CoreLib/src/System/Resources/ResourceManager.cs b/src/libraries/System.Private.CoreLib/src/System/Resources/ResourceManager.cs index 25cd61020bd910..5727c717405c37 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Resources/ResourceManager.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Resources/ResourceManager.cs @@ -505,7 +505,7 @@ private static void AddResourceSet(Dictionary localResource // If another thread added this culture, return that. if (localResourceSets.TryGetValue(cultureName, out ResourceSet? lostRace)) { - if (!object.ReferenceEquals(lostRace, rs)) + if (!ReferenceEquals(lostRace, rs)) { // Note: In certain cases, we can be trying to add a ResourceSet for multiple // cultures on one thread, while a second thread added another ResourceSet for one @@ -776,7 +776,7 @@ internal Version? SatelliteContractVersion } internal static Version? ObtainSatelliteContractVersion(Assembly a) => - ResourceManager.GetSatelliteContractVersion(a); + GetSatelliteContractVersion(a); internal UltimateResourceFallbackLocation FallbackLoc { diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/AmbiguousImplementationException.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/AmbiguousImplementationException.cs index 692a26884d4875..d5a85c2eef3ace 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/AmbiguousImplementationException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/AmbiguousImplementationException.cs @@ -1,16 +1,17 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Runtime { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("System.Runtime, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] + [TypeForwardedFrom("System.Runtime, Version=4.2.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")] public sealed class AmbiguousImplementationException : Exception { public AmbiguousImplementationException() - : base(SR.AmbiguousImplementationException_NullMessage) + : base(SR.Arg_AmbiguousImplementationException_NoMessage) { HResult = HResults.COR_E_AMBIGUOUSIMPLEMENTATION; } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncTaskMethodBuilder.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncTaskMethodBuilder.cs index 9936ab840f3a62..c0899ab80f406c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncTaskMethodBuilder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncTaskMethodBuilder.cs @@ -7,7 +7,7 @@ namespace System.Runtime.CompilerServices { /// - /// Provides a builder for asynchronous methods that return . + /// Provides a builder for asynchronous methods that return . /// This type is intended for compiler use only. /// /// @@ -34,8 +34,8 @@ public void Start(ref TStateMachine stateMachine) where TStateMac /// Associates the builder with the state machine it represents. /// The heap-allocated state machine object. - /// The argument was null (Nothing in Visual Basic). - /// The builder is incorrectly initialized. + /// The argument was null (Nothing in Visual Basic). + /// The builder is incorrectly initialized. public void SetStateMachine(IAsyncStateMachine stateMachine) => AsyncMethodBuilderCore.SetStateMachine(stateMachine, task: null); @@ -66,9 +66,9 @@ public void AwaitUnsafeOnCompleted( where TStateMachine : IAsyncStateMachine => AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine, ref m_task); - /// Gets the for this builder. - /// The representing the builder's asynchronous operation. - /// The builder is not initialized. + /// Gets the for this builder. + /// The representing the builder's asynchronous operation. + /// The builder is not initialized. public Task Task { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -88,11 +88,11 @@ private Task InitializeTaskAsPromise() } /// - /// Completes the in the - /// RanToCompletion state. + /// Completes the in the + /// RanToCompletion state. /// - /// The builder is not initialized. - /// The task has already completed. + /// The builder is not initialized. + /// The task has already completed. public void SetResult() { // Get the currently stored task, which will be non-null if get_Task has already been accessed. @@ -109,13 +109,13 @@ public void SetResult() } /// - /// Completes the in the - /// Faulted state with the specified exception. + /// Completes the in the + /// Faulted state with the specified exception. /// - /// The to use to fault the task. - /// The argument is null (Nothing in Visual Basic). - /// The builder is not initialized. - /// The task has already completed. + /// The to use to fault the task. + /// The argument is null (Nothing in Visual Basic). + /// The builder is not initialized. + /// The task has already completed. public void SetException(Exception exception) => AsyncTaskMethodBuilder.SetException(exception, ref m_task); 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 8251270eb5041c..443b8993612a56 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 @@ -9,7 +9,7 @@ namespace System.Runtime.CompilerServices { /// - /// Provides a builder for asynchronous methods that return . + /// Provides a builder for asynchronous methods that return . /// This type is intended for compiler use only. /// /// @@ -36,8 +36,8 @@ public void Start(ref TStateMachine stateMachine) where TStateMac /// Associates the builder with the state machine it represents. /// The heap-allocated state machine object. - /// The argument was null (Nothing in Visual Basic). - /// The builder is incorrectly initialized. + /// The argument was null (Nothing in Visual Basic). + /// The builder is incorrectly initialized. public void SetStateMachine(IAsyncStateMachine stateMachine) => AsyncMethodBuilderCore.SetStateMachine(stateMachine, m_task); @@ -65,7 +65,7 @@ internal static void AwaitOnCompleted( } catch (Exception e) { - System.Threading.Tasks.Task.ThrowAsync(e, targetContext: null); + Threading.Tasks.Task.ThrowAsync(e, targetContext: null); } } @@ -109,7 +109,7 @@ internal static void AwaitUnsafeOnCompleted( else if ((null != (object?)default(TAwaiter)) && (awaiter is IConfiguredTaskAwaiter)) { ref ConfiguredTaskAwaitable.ConfiguredTaskAwaiter ta = ref Unsafe.As(ref awaiter); - TaskAwaiter.UnsafeOnCompletedInternal(ta.m_task, box, ta.m_continueOnCapturedContext); + TaskAwaiter.UnsafeOnCompletedInternal(ta.m_task, box, (ta.m_options & ConfigureAwaitOptions.ContinueOnCapturedContext) != 0); } else if ((null != (object?)default(TAwaiter)) && (awaiter is IStateMachineBoxAwareAwaiter)) { @@ -126,7 +126,7 @@ internal static void AwaitUnsafeOnCompleted( // exceptions well at that location in the state machine, especially if the exception may occur // after the ValueTaskAwaiter already successfully hooked up the callback, in which case it's possible // two different flows of execution could end up happening in the same async method call. - System.Threading.Tasks.Task.ThrowAsync(e, targetContext: null); + Threading.Tasks.Task.ThrowAsync(e, targetContext: null); } } else @@ -138,7 +138,7 @@ internal static void AwaitUnsafeOnCompleted( } catch (Exception e) { - System.Threading.Tasks.Task.ThrowAsync(e, targetContext: null); + Threading.Tasks.Task.ThrowAsync(e, targetContext: null); } } } @@ -230,9 +230,9 @@ private static IAsyncStateMachineBox GetStateMachineBox( } // And if async debugging is enabled, track the task. - if (System.Threading.Tasks.Task.s_asyncDebuggingEnabled) + if (Threading.Tasks.Task.s_asyncDebuggingEnabled) { - System.Threading.Tasks.Task.AddToActiveTasks(box); + Threading.Tasks.Task.AddToActiveTasks(box); } return box; @@ -333,7 +333,7 @@ public ref ExecutionContext? Context { get { - Debug.Assert(m_stateObject is null || m_stateObject is ExecutionContext, $"{nameof(m_stateObject)} must only be for ExecutionContext but contained {m_stateObject}."); + Debug.Assert(m_stateObject is null or ExecutionContext, $"Expected {nameof(m_stateObject)} to be null or an ExecutionContext but was {(m_stateObject is object o ? o.GetType().ToString() : "(null)")}."); return ref Unsafe.As(ref m_stateObject); } } @@ -417,8 +417,8 @@ public void ClearStateUponCompletion() IAsyncStateMachine IAsyncStateMachineBox.GetStateMachineObject() => StateMachine!; // likely boxes, only use for debugging } - /// Gets the for this builder. - /// The representing the builder's asynchronous operation. + /// Gets the for this builder. + /// The representing the builder's asynchronous operation. public Task Task { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -453,11 +453,11 @@ internal static Task CreateWeaklyTypedStateMachineBox() } /// - /// Completes the in the - /// RanToCompletion state with the specified result. + /// Completes the in the + /// RanToCompletion state with the specified result. /// /// The result to use to complete the task. - /// The task has already completed. + /// The task has already completed. public void SetResult(TResult result) { // Get the currently stored task, which will be non-null if get_Task has already been accessed. @@ -492,12 +492,12 @@ internal static void SetExistingTaskResult(Task task, TResult? result) } /// - /// Completes the in the - /// Faulted state with the specified exception. + /// Completes the in the + /// Faulted state with the specified exception. /// - /// The to use to fault the task. - /// The argument is null (Nothing in Visual Basic). - /// The task has already completed. + /// The to use to fault the task. + /// The argument is null (Nothing in Visual Basic). + /// The task has already completed. public void SetException(Exception exception) => SetException(exception, ref m_task); internal static void SetException(Exception exception, ref Task? taskField) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncVoidMethodBuilder.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncVoidMethodBuilder.cs index 0800965240718a..98b2a30fd52e90 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncVoidMethodBuilder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/AsyncVoidMethodBuilder.cs @@ -33,7 +33,7 @@ public static AsyncVoidMethodBuilder Create() /// Initiates the builder's execution with the associated state machine. /// Specifies the type of the state machine. /// The state machine instance, passed by reference. - /// The argument was null (Nothing in Visual Basic). + /// The argument was null (Nothing in Visual Basic). [DebuggerStepThrough] [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Start(ref TStateMachine stateMachine) where TStateMachine : IAsyncStateMachine => @@ -41,8 +41,8 @@ public void Start(ref TStateMachine stateMachine) where TStateMac /// Associates the builder with the state machine it represents. /// The heap-allocated state machine object. - /// The argument was null (Nothing in Visual Basic). - /// The builder is incorrectly initialized. + /// The argument was null (Nothing in Visual Basic). + /// The builder is incorrectly initialized. public void SetStateMachine(IAsyncStateMachine stateMachine) => _builder.SetStateMachine(stateMachine); @@ -92,8 +92,8 @@ public void SetResult() /// Faults the method builder with an exception. /// The exception that is the cause of this fault. - /// The argument is null (Nothing in Visual Basic). - /// The builder is not initialized. + /// The argument is null (Nothing in Visual Basic). + /// The builder is not initialized. public void SetException(Exception exception) { if (exception == null) @@ -112,7 +112,7 @@ public void SetException(Exception exception) // and decrement its outstanding operation count. try { - System.Threading.Tasks.Task.ThrowAsync(exception, targetContext: _synchronizationContext); + Task.ThrowAsync(exception, targetContext: _synchronizationContext); } finally { @@ -124,7 +124,7 @@ public void SetException(Exception exception) // Otherwise, queue the exception to be thrown on the ThreadPool. This will // result in a crash unless legacy exception behavior is enabled by a config // file or a CLR host. - System.Threading.Tasks.Task.ThrowAsync(exception, targetContext: null); + Task.ThrowAsync(exception, targetContext: null); } // The exception was propagated already; we don't need or want to fault the builder, just mark it as completed. diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/CallingConventions.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/CallingConventions.cs index a501994645a9f9..e4870a1fcc4d64 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/CallingConventions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/CallingConventions.cs @@ -20,7 +20,7 @@ public CallConvStdcall() { } /// Indicates that a method should suppress the GC transition as part of the calling convention. /// /// - /// The describes the effects + /// The describes the effects /// of suppressing the GC transition on a native call. /// public class CallConvSuppressGCTransition diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastCache.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastCache.cs index fe581419ea45bb..a333b710d012c1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastCache.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/CastCache.cs @@ -152,32 +152,16 @@ internal static CastResult TryGet(nuint source, nuint target) // we must read in this order: version -> [entry parts] -> version // if version is odd or changes, the entry is inconsistent and thus ignored uint version = Volatile.Read(ref pEntry._version); - -#if CORECLR - // in CoreCLR we do ordinary reads of the entry parts and - // Interlocked.ReadMemoryBarrier() before reading the version nuint entrySource = pEntry._source; -#else - // must read this before reading the version again - nuint entrySource = Volatile.Read(ref pEntry._source); -#endif - // mask the lower version bit to make it even. // This way we can check if version is odd or changing in just one compare. version &= unchecked((uint)~1); if (entrySource == source) { - -#if CORECLR // in CoreCLR we do ordinary reads of the entry parts and // Interlocked.ReadMemoryBarrier() before reading the version nuint entryTargetAndResult = pEntry._targetAndResult; -#else - // must read this before reading the version again - nuint entryTargetAndResult = Volatile.Read(ref pEntry._targetAndResult); -#endif - // target never has its lower bit set. // a matching entryTargetAndResult would the have same bits, except for the lowest one, which is the result. entryTargetAndResult ^= target; @@ -189,10 +173,7 @@ internal static CastResult TryGet(nuint source, nuint target) // - use acquires for both _source and _targetAndResults or // - issue a load barrier before reading _version // benchmarks on available hardware (Jan 2020) show that use of a read barrier is cheaper. - -#if CORECLR Interlocked.ReadMemoryBarrier(); -#endif if (version != pEntry._version) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ContractHelper.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ContractHelper.cs index 5a50a0989a2650..a6812604556f15 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ContractHelper.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ContractHelper.cs @@ -3,6 +3,7 @@ #define DEBUG // The behavior of this contract library should be consistent regardless of build type. +using System.Diagnostics; using System.Diagnostics.Contracts; namespace System.Runtime.CompilerServices @@ -28,7 +29,7 @@ public static class ContractHelper /// On exit: null if the event was handled and should not trigger a failure. /// Otherwise, returns the localized failure message. /// - [System.Diagnostics.DebuggerNonUserCode] + [DebuggerNonUserCode] public static string? RaiseContractFailedEvent(ContractFailureKind failureKind, string? userMessage, string? conditionText, Exception? innerException) { if (failureKind < ContractFailureKind.Precondition || failureKind > ContractFailureKind.Assume) @@ -83,7 +84,7 @@ public static class ContractHelper /// /// Rewriter calls this method to get the default failure behavior. /// - [System.Diagnostics.DebuggerNonUserCode] + [DebuggerNonUserCode] public static void TriggerFailure(ContractFailureKind kind, string? displayMessage, string? userMessage, string? conditionText, Exception? innerException) { if (string.IsNullOrEmpty(displayMessage)) @@ -91,7 +92,7 @@ public static void TriggerFailure(ContractFailureKind kind, string? displayMessa displayMessage = GetDisplayMessage(kind, userMessage, conditionText); } - System.Diagnostics.Debug.ContractFailure(displayMessage, string.Empty, GetFailureMessage(kind, null)); + Debug.ContractFailure(displayMessage, string.Empty, GetFailureMessage(kind, null)); } private static string GetFailureMessage(ContractFailureKind failureKind, string? conditionText) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/EnumeratorCancellationAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/EnumeratorCancellationAttribute.cs index 25772639ac6610..d43f1b456899ab 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/EnumeratorCancellationAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/EnumeratorCancellationAttribute.cs @@ -3,7 +3,7 @@ namespace System.Runtime.CompilerServices { - [System.AttributeUsage(AttributeTargets.Parameter, Inherited = false)] + [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] public sealed class EnumeratorCancellationAttribute : Attribute { public EnumeratorCancellationAttribute() diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/INotifyCompletion.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/INotifyCompletion.cs index 64ad5fc9cab38e..c61dd1b0c2f371 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/INotifyCompletion.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/INotifyCompletion.cs @@ -17,7 +17,7 @@ public interface INotifyCompletion { /// Schedules the continuation action to be invoked when the instance completes. /// The action to invoke when the operation completes. - /// The argument is null (Nothing in Visual Basic). + /// The argument is null (Nothing in Visual Basic). void OnCompleted(Action continuation); } @@ -28,7 +28,7 @@ public interface ICriticalNotifyCompletion : INotifyCompletion { /// Schedules the continuation action to be invoked when the instance completes. /// The action to invoke when the operation completes. - /// The argument is null (Nothing in Visual Basic). + /// The argument is null (Nothing in Visual Basic). /// Unlike OnCompleted, UnsafeOnCompleted need not propagate ExecutionContext information. void UnsafeOnCompleted(Action continuation); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/MetadataUpdateOriginalTypeAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/MetadataUpdateOriginalTypeAttribute.cs index c7ec6e786d9f53..578247f7f85a7f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/MetadataUpdateOriginalTypeAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/MetadataUpdateOriginalTypeAttribute.cs @@ -3,17 +3,17 @@ namespace System.Runtime.CompilerServices; -[AttributeUsage(System.AttributeTargets.Class | System.AttributeTargets.Struct, +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple=false, Inherited=false)] public class MetadataUpdateOriginalTypeAttribute : Attribute { /// This attribute is emitted by Roslyn when a type that is marked with (or derives /// from a type that is marked with) is updated + /// cref="CreateNewOnMetadataUpdateAttribute" /> is updated /// during a hot reload session. The points to the original version /// of the updated type. The next update of the type will have the same . Frameworks that provide support for hot reload by implementing a - /// may use this + /// may use this /// attribute to relate an updated type to its original version. /// /// The original type that was updated diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/PoolingAsyncValueTaskMethodBuilderT.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/PoolingAsyncValueTaskMethodBuilderT.cs index b5f01e81feb3cc..150f22c1970325 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/PoolingAsyncValueTaskMethodBuilderT.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/PoolingAsyncValueTaskMethodBuilderT.cs @@ -93,7 +93,7 @@ public ValueTask Task // "work" but in a degraded mode, as we don't know the TStateMachine type here, and thus we use a box around // the interface instead. - PoolingAsyncValueTaskMethodBuilder.StateMachineBox? box = m_task ??= CreateWeaklyTypedStateMachineBox(); + StateMachineBox? box = m_task ??= CreateWeaklyTypedStateMachineBox(); return new ValueTask(box, box.Version); } } @@ -119,7 +119,7 @@ internal static void AwaitOnCompleted( } catch (Exception e) { - System.Threading.Tasks.Task.ThrowAsync(e, targetContext: null); + Threading.Tasks.Task.ThrowAsync(e, targetContext: null); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/QCallHandles.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/QCallHandles.cs index 7bd401ef58f757..240e9932bf6244 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/QCallHandles.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/QCallHandles.cs @@ -51,13 +51,13 @@ internal unsafe ref struct QCallModule private void* _ptr; private IntPtr _module; - internal QCallModule(ref System.Reflection.RuntimeModule module) + internal QCallModule(ref Reflection.RuntimeModule module) { _ptr = Unsafe.AsPointer(ref module); _module = module.GetUnderlyingNativeHandle(); } - internal QCallModule(ref System.Reflection.Emit.RuntimeModuleBuilder module) + internal QCallModule(ref Reflection.Emit.RuntimeModuleBuilder module) { _ptr = Unsafe.AsPointer(ref module); _module = module.InternalModule.GetUnderlyingNativeHandle(); @@ -70,7 +70,7 @@ internal unsafe ref struct QCallAssembly private void* _ptr; private IntPtr _assembly; - internal QCallAssembly(ref System.Reflection.RuntimeAssembly assembly) + internal QCallAssembly(ref Reflection.RuntimeAssembly assembly) { _ptr = Unsafe.AsPointer(ref assembly); _assembly = assembly?.GetUnderlyingNativeHandle() ?? IntPtr.Zero; @@ -83,13 +83,13 @@ internal unsafe ref struct QCallTypeHandle private void* _ptr; private IntPtr _handle; - internal QCallTypeHandle(ref System.RuntimeType type) + internal QCallTypeHandle(ref RuntimeType type) { _ptr = Unsafe.AsPointer(ref type); _handle = type?.GetUnderlyingNativeHandle() ?? IntPtr.Zero; } - internal QCallTypeHandle(ref System.RuntimeTypeHandle rth) + internal QCallTypeHandle(ref RuntimeTypeHandle rth) { _ptr = Unsafe.AsPointer(ref rth); _handle = rth.Value; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeWrappedException.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeWrappedException.cs index e1c5af0e34daea..92fee17c4a4b98 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeWrappedException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeWrappedException.cs @@ -10,7 +10,7 @@ namespace System.Runtime.CompilerServices /// Exception used to wrap all non-CLS compliant exceptions. /// [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class RuntimeWrappedException : Exception { private readonly object _wrappedException; // EE expects this name diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/TaskAwaiter.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/TaskAwaiter.cs index d17078df3999a4..6279188504fbb6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/TaskAwaiter.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/TaskAwaiter.cs @@ -1,41 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// =+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ -// -// -// -// Types for awaiting Task and Task. These types are emitted from Task{}.GetAwaiter -// and Task{}.ConfigureAwait. They are meant to be used only by the compiler, e.g. -// -// await nonGenericTask; -// ===================== -// var $awaiter = nonGenericTask.GetAwaiter(); -// if (!$awaiter.IsCompleted) -// { -// SPILL: -// $builder.AwaitUnsafeOnCompleted(ref $awaiter, ref this); -// return; -// Label: -// UNSPILL; -// } -// $awaiter.GetResult(); -// -// result += await genericTask.ConfigureAwait(false); -// =================================================================================== -// var $awaiter = genericTask.ConfigureAwait(false).GetAwaiter(); -// if (!$awaiter.IsCompleted) -// { -// SPILL; -// $builder.AwaitUnsafeOnCompleted(ref $awaiter, ref this); -// return; -// Label: -// UNSPILL; -// } -// result += $awaiter.GetResult(); -// -// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- - using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Tracing; @@ -51,7 +16,7 @@ namespace System.Runtime.CompilerServices { - /// Provides an awaiter for awaiting a . + /// Provides an awaiter for awaiting a . public readonly struct TaskAwaiter : ICriticalNotifyCompletion, ITaskAwaiter { // WARNING: Unsafe.As is used to access the generic TaskAwaiter<> as TaskAwaiter. @@ -61,7 +26,7 @@ namespace System.Runtime.CompilerServices internal readonly Task m_task; /// Initializes the . - /// The to be awaited. + /// The to be awaited. internal TaskAwaiter(Task task) { Debug.Assert(task != null, "Constructing an awaiter requires a task to await."); @@ -70,33 +35,33 @@ internal TaskAwaiter(Task task) /// Gets whether the task being awaited is completed. /// This property is intended for compiler user rather than use directly in code. - /// The awaiter was not properly initialized. + /// The awaiter was not properly initialized. public bool IsCompleted => m_task.IsCompleted; - /// Schedules the continuation onto the associated with this . + /// Schedules the continuation onto the associated with this . /// The action to invoke when the await operation completes. - /// The argument is null (Nothing in Visual Basic). - /// The awaiter was not properly initialized. + /// The argument is null (Nothing in Visual Basic). + /// The awaiter was not properly initialized. /// This method is intended for compiler use rather than use directly in code. public void OnCompleted(Action continuation) { OnCompletedInternal(m_task, continuation, continueOnCapturedContext: true, flowExecutionContext: true); } - /// Schedules the continuation onto the associated with this . + /// Schedules the continuation onto the associated with this . /// The action to invoke when the await operation completes. - /// The argument is null (Nothing in Visual Basic). - /// The awaiter was not properly initialized. + /// The argument is null (Nothing in Visual Basic). + /// The awaiter was not properly initialized. /// This method is intended for compiler use rather than use directly in code. public void UnsafeOnCompleted(Action continuation) { OnCompletedInternal(m_task, continuation, continueOnCapturedContext: true, flowExecutionContext: false); } - /// Ends the await on the completed . - /// The awaiter was not properly initialized. - /// The task was canceled. - /// The task completed in a Faulted state. + /// Ends the await on the completed . + /// The awaiter was not properly initialized. + /// The task was canceled. + /// The task completed in a Faulted state. [StackTraceHidden] public void GetResult() { @@ -108,15 +73,17 @@ public void GetResult() /// prior to completing the await. /// /// The awaited task. + /// The options used to configure an await. [StackTraceHidden] - internal static void ValidateEnd(Task task) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static void ValidateEnd(Task task, ConfigureAwaitOptions options = ConfigureAwaitOptions.None) { // Fast checks that can be inlined. if (task.IsWaitNotificationEnabledOrNotRanToCompletion) { // If either the end await bit is set or we're not completed successfully, // fall back to the slower path. - HandleNonSuccessAndDebuggerNotification(task); + HandleNonSuccessAndDebuggerNotification(task, options); } } @@ -125,12 +92,11 @@ internal static void ValidateEnd(Task task) /// the await on the task, and throws an exception if the task did not complete successfully. /// /// The awaited task. + /// The options used to configure an await. [StackTraceHidden] - private static void HandleNonSuccessAndDebuggerNotification(Task task) + [MethodImpl(MethodImplOptions.NoInlining)] + private static void HandleNonSuccessAndDebuggerNotification(Task task, ConfigureAwaitOptions options) { - // NOTE: The JIT refuses to inline ValidateEnd when it contains the contents - // of HandleNonSuccessAndDebuggerNotification, hence the separation. - // Synchronously wait for the task to complete. When used by the compiler, // the task will already be complete. This code exists only for direct GetResult use, // for cases where the same exception propagation semantics used by "await" are desired, @@ -145,7 +111,15 @@ private static void HandleNonSuccessAndDebuggerNotification(Task task) task.NotifyDebuggerOfWaitCompletionIfNecessary(); // And throw an exception if the task is faulted or canceled. - if (!task.IsCompletedSuccessfully) ThrowForNonSuccess(task); + if (!task.IsCompletedSuccessfully) + { + if ((options & ConfigureAwaitOptions.SuppressThrowing) == 0) + { + ThrowForNonSuccess(task); + } + + task.MarkExceptionsAsHandled(); + } } /// Throws an exception to handle a task that completed in a state other than RanToCompletion. @@ -189,13 +163,13 @@ private static void ThrowForNonSuccess(Task task) } } - /// Schedules the continuation onto the associated with this . + /// Schedules the continuation onto the associated with this . /// The task being awaited. /// The action to invoke when the await operation completes. /// Whether to capture and marshal back to the current context. /// Whether to flow ExecutionContext across the await. - /// The argument is null (Nothing in Visual Basic). - /// The awaiter was not properly initialized. + /// The argument is null (Nothing in Visual Basic). + /// The awaiter was not properly initialized. /// This method is intended for compiler use rather than use directly in code. internal static void OnCompletedInternal(Task task, Action continuation, bool continueOnCapturedContext, bool flowExecutionContext) { @@ -212,7 +186,7 @@ internal static void OnCompletedInternal(Task task, Action continuation, bool co task.SetContinuationForAwait(continuation, continueOnCapturedContext, flowExecutionContext); } - /// Schedules the continuation onto the associated with this . + /// Schedules the continuation onto the associated with this . /// The task being awaited. /// The box to invoke when the await operation completes. /// Whether to capture and marshal back to the current context. @@ -308,7 +282,7 @@ private static Action OutputWaitEtwEvents(Task task, Action continuation) } } - /// Provides an awaiter for awaiting a . + /// Provides an awaiter for awaiting a . public readonly struct TaskAwaiter : ICriticalNotifyCompletion, ITaskAwaiter { // WARNING: Unsafe.As is used to access TaskAwaiter<> as the non-generic TaskAwaiter. @@ -318,7 +292,7 @@ private static Action OutputWaitEtwEvents(Task task, Action continuation) private readonly Task m_task; /// Initializes the . - /// The to be awaited. + /// The to be awaited. internal TaskAwaiter(Task task) { Debug.Assert(task != null, "Constructing an awaiter requires a task to await."); @@ -327,34 +301,34 @@ internal TaskAwaiter(Task task) /// Gets whether the task being awaited is completed. /// This property is intended for compiler user rather than use directly in code. - /// The awaiter was not properly initialized. + /// The awaiter was not properly initialized. public bool IsCompleted => m_task.IsCompleted; - /// Schedules the continuation onto the associated with this . + /// Schedules the continuation onto the associated with this . /// The action to invoke when the await operation completes. - /// The argument is null (Nothing in Visual Basic). - /// The awaiter was not properly initialized. + /// The argument is null (Nothing in Visual Basic). + /// The awaiter was not properly initialized. /// This method is intended for compiler use rather than use directly in code. public void OnCompleted(Action continuation) { TaskAwaiter.OnCompletedInternal(m_task, continuation, continueOnCapturedContext: true, flowExecutionContext: true); } - /// Schedules the continuation onto the associated with this . + /// Schedules the continuation onto the associated with this . /// The action to invoke when the await operation completes. - /// The argument is null (Nothing in Visual Basic). - /// The awaiter was not properly initialized. + /// The argument is null (Nothing in Visual Basic). + /// The awaiter was not properly initialized. /// This method is intended for compiler use rather than use directly in code. public void UnsafeOnCompleted(Action continuation) { TaskAwaiter.OnCompletedInternal(m_task, continuation, continueOnCapturedContext: true, flowExecutionContext: false); } - /// Ends the await on the completed . - /// The result of the completed . - /// The awaiter was not properly initialized. - /// The task was canceled. - /// The task completed in a Faulted state. + /// Ends the await on the completed . + /// The result of the completed . + /// The awaiter was not properly initialized. + /// The task was canceled. + /// The task completed in a Faulted state. [StackTraceHidden] public TResult GetResult() { @@ -377,27 +351,25 @@ internal interface ITaskAwaiter { } /// internal interface IConfiguredTaskAwaiter { } - /// Provides an awaitable object that allows for configured awaits on . + /// Provides an awaitable object that allows for configured awaits on . /// This type is intended for compiler use only. public readonly struct ConfiguredTaskAwaitable { /// The task being awaited. - private readonly ConfiguredTaskAwaitable.ConfiguredTaskAwaiter m_configuredTaskAwaiter; + private readonly ConfiguredTaskAwaiter m_configuredTaskAwaiter; /// Initializes the . - /// The awaitable . - /// - /// true to attempt to marshal the continuation back to the original context captured; otherwise, false. - /// - internal ConfiguredTaskAwaitable(Task task, bool continueOnCapturedContext) + /// The awaitable . + /// Options to control the behavior of the awaiter. + internal ConfiguredTaskAwaitable(Task task, ConfigureAwaitOptions options) { Debug.Assert(task != null, "Constructing an awaitable requires a task to await."); - m_configuredTaskAwaiter = new ConfiguredTaskAwaitable.ConfiguredTaskAwaiter(task, continueOnCapturedContext); + m_configuredTaskAwaiter = new ConfiguredTaskAwaiter(task, options); } /// Gets an awaiter for this awaitable. /// The awaiter. - public ConfiguredTaskAwaitable.ConfiguredTaskAwaiter GetAwaiter() + public ConfiguredTaskAwaiter GetAwaiter() { return m_configuredTaskAwaiter; } @@ -411,79 +383,75 @@ public ConfiguredTaskAwaitable.ConfiguredTaskAwaiter GetAwaiter() /// The task being awaited. internal readonly Task m_task; - /// Whether to attempt marshaling back to the original context. - internal readonly bool m_continueOnCapturedContext; + /// Options for how this awaiter behaves. This is a bit field with values from . + internal readonly ConfigureAwaitOptions m_options; /// Initializes the . - /// The to await. - /// - /// true to attempt to marshal the continuation back to the original context captured - /// when BeginAwait is called; otherwise, false. - /// - internal ConfiguredTaskAwaiter(Task task, bool continueOnCapturedContext) + /// The to await. + /// Options used to configure how an await is performed. + internal ConfiguredTaskAwaiter(Task task, ConfigureAwaitOptions options) { Debug.Assert(task != null, "Constructing an awaiter requires a task to await."); + Debug.Assert((options & ~(ConfigureAwaitOptions.ContinueOnCapturedContext | ConfigureAwaitOptions.SuppressThrowing | ConfigureAwaitOptions.ForceYielding)) == 0); m_task = task; - m_continueOnCapturedContext = continueOnCapturedContext; + m_options = options; } /// Gets whether the task being awaited is completed. /// This property is intended for compiler user rather than use directly in code. - /// The awaiter was not properly initialized. - public bool IsCompleted => m_task.IsCompleted; + /// The awaiter was not properly initialized. + public bool IsCompleted => ((m_options & ConfigureAwaitOptions.ForceYielding) == 0) && m_task.IsCompleted; - /// Schedules the continuation onto the associated with this . + /// Schedules the continuation onto the associated with this . /// The action to invoke when the await operation completes. - /// The argument is null (Nothing in Visual Basic). - /// The awaiter was not properly initialized. + /// The argument is null (Nothing in Visual Basic). + /// The awaiter was not properly initialized. /// This method is intended for compiler use rather than use directly in code. public void OnCompleted(Action continuation) { - TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext: true); + TaskAwaiter.OnCompletedInternal(m_task, continuation, (m_options & ConfigureAwaitOptions.ContinueOnCapturedContext) != 0, flowExecutionContext: true); } - /// Schedules the continuation onto the associated with this . + /// Schedules the continuation onto the associated with this . /// The action to invoke when the await operation completes. - /// The argument is null (Nothing in Visual Basic). - /// The awaiter was not properly initialized. + /// The argument is null (Nothing in Visual Basic). + /// The awaiter was not properly initialized. /// This method is intended for compiler use rather than use directly in code. public void UnsafeOnCompleted(Action continuation) { - TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext: false); + TaskAwaiter.OnCompletedInternal(m_task, continuation, (m_options & ConfigureAwaitOptions.ContinueOnCapturedContext) != 0, flowExecutionContext: false); } - /// Ends the await on the completed . - /// The awaiter was not properly initialized. - /// The task was canceled. - /// The task completed in a Faulted state. + /// Ends the await on the completed . + /// The awaiter was not properly initialized. + /// The task was canceled. + /// The task completed in a Faulted state. [StackTraceHidden] public void GetResult() { - TaskAwaiter.ValidateEnd(m_task); + TaskAwaiter.ValidateEnd(m_task, m_options); } } } - /// Provides an awaitable object that allows for configured awaits on . + /// Provides an awaitable object that allows for configured awaits on . /// This type is intended for compiler use only. public readonly struct ConfiguredTaskAwaitable { /// The underlying awaitable on whose logic this awaitable relies. - private readonly ConfiguredTaskAwaitable.ConfiguredTaskAwaiter m_configuredTaskAwaiter; + private readonly ConfiguredTaskAwaiter m_configuredTaskAwaiter; /// Initializes the . - /// The awaitable . - /// - /// true to attempt to marshal the continuation back to the original context captured; otherwise, false. - /// - internal ConfiguredTaskAwaitable(Task task, bool continueOnCapturedContext) + /// The awaitable . + /// Options to control the behavior of the awaiter. + internal ConfiguredTaskAwaitable(Task task, ConfigureAwaitOptions options) { - m_configuredTaskAwaiter = new ConfiguredTaskAwaitable.ConfiguredTaskAwaiter(task, continueOnCapturedContext); + m_configuredTaskAwaiter = new ConfiguredTaskAwaiter(task, options); } /// Gets an awaiter for this awaitable. /// The awaiter. - public ConfiguredTaskAwaitable.ConfiguredTaskAwaiter GetAwaiter() + public ConfiguredTaskAwaiter GetAwaiter() { return m_configuredTaskAwaiter; } @@ -497,55 +465,54 @@ public ConfiguredTaskAwaitable.ConfiguredTaskAwaiter GetAwaiter() /// The task being awaited. private readonly Task m_task; - /// Whether to attempt marshaling back to the original context. - private readonly bool m_continueOnCapturedContext; + /// Options for how this awaiter behaves. This is a bit field with values from . + internal readonly ConfigureAwaitOptions m_options; /// Initializes the . - /// The awaitable . - /// - /// true to attempt to marshal the continuation back to the original context captured; otherwise, false. - /// - internal ConfiguredTaskAwaiter(Task task, bool continueOnCapturedContext) + /// The awaitable . + /// The options used to configure the await's behavior. + internal ConfiguredTaskAwaiter(Task task, ConfigureAwaitOptions options) { Debug.Assert(task != null, "Constructing an awaiter requires a task to await."); + Debug.Assert((options & ~(ConfigureAwaitOptions.ContinueOnCapturedContext | ConfigureAwaitOptions.ForceYielding)) == 0); m_task = task; - m_continueOnCapturedContext = continueOnCapturedContext; + m_options = options; } /// Gets whether the task being awaited is completed. /// This property is intended for compiler user rather than use directly in code. - /// The awaiter was not properly initialized. - public bool IsCompleted => m_task.IsCompleted; + /// The awaiter was not properly initialized. + public bool IsCompleted => ((m_options & ConfigureAwaitOptions.ForceYielding) == 0) && m_task.IsCompleted; - /// Schedules the continuation onto the associated with this . + /// Schedules the continuation onto the associated with this . /// The action to invoke when the await operation completes. - /// The argument is null (Nothing in Visual Basic). - /// The awaiter was not properly initialized. + /// The argument is null (Nothing in Visual Basic). + /// The awaiter was not properly initialized. /// This method is intended for compiler use rather than use directly in code. public void OnCompleted(Action continuation) { - TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext: true); + TaskAwaiter.OnCompletedInternal(m_task, continuation, (m_options & ConfigureAwaitOptions.ContinueOnCapturedContext) != 0, flowExecutionContext: true); } - /// Schedules the continuation onto the associated with this . + /// Schedules the continuation onto the associated with this . /// The action to invoke when the await operation completes. - /// The argument is null (Nothing in Visual Basic). - /// The awaiter was not properly initialized. + /// The argument is null (Nothing in Visual Basic). + /// The awaiter was not properly initialized. /// This method is intended for compiler use rather than use directly in code. public void UnsafeOnCompleted(Action continuation) { - TaskAwaiter.OnCompletedInternal(m_task, continuation, m_continueOnCapturedContext, flowExecutionContext: false); + TaskAwaiter.OnCompletedInternal(m_task, continuation, (m_options & ConfigureAwaitOptions.ContinueOnCapturedContext) != 0, flowExecutionContext: false); } - /// Ends the await on the completed . - /// The result of the completed . - /// The awaiter was not properly initialized. - /// The task was canceled. - /// The task completed in a Faulted state. + /// Ends the await on the completed . + /// The result of the completed . + /// The awaiter was not properly initialized. + /// The task was canceled. + /// The task completed in a Faulted state. [StackTraceHidden] public TResult GetResult() { - TaskAwaiter.ValidateEnd(m_task); + TaskAwaiter.ValidateEnd(m_task); // no need to pass options as SuppressThrowing isn't supported return m_task.ResultOnSuccess; } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/TupleElementNamesAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/TupleElementNamesAttribute.cs index ea3ddee5539056..9f8e6f92402a4d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/TupleElementNamesAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/TupleElementNamesAttribute.cs @@ -6,7 +6,7 @@ namespace System.Runtime.CompilerServices { /// - /// Indicates that the use of on a member is meant to be treated as a tuple with element names. + /// Indicates that the use of on a member is meant to be treated as a tuple with element names. /// [CLSCompliant(false)] [AttributeUsage(AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue | AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Event)] @@ -20,16 +20,16 @@ public sealed class TupleElementNamesAttribute : Attribute /// /// /// Specifies, in a pre-order depth-first traversal of a type's - /// construction, which occurrences are + /// construction, which occurrences are /// meant to carry element names. /// /// /// This constructor is meant to be used on types that contain an - /// instantiation of that contains + /// instantiation of that contains /// element names. For instance, if C is a generic type with /// two type parameters, then a use of the constructed type C{, might be intended to + /// cref="ValueTuple{T1, T2}"/>, might be intended to /// treat the first type argument as a tuple with element names and the /// second as a tuple without element names. In which case, the /// appropriate attribute specification should use a @@ -45,7 +45,7 @@ public TupleElementNamesAttribute(string?[] transformNames) /// /// Specifies, in a pre-order depth-first traversal of a type's - /// construction, which elements are + /// construction, which elements are /// meant to carry element names. /// public IList TransformNames => _transformNames; diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/YieldAwaitable.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/YieldAwaitable.cs index b7033ad77d8574..2a42c88c41d96e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/YieldAwaitable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/YieldAwaitable.cs @@ -51,7 +51,7 @@ public readonly struct YieldAwaitable /// Posts the back to the current context. /// The action to invoke asynchronously. - /// The argument is null (Nothing in Visual Basic). + /// The argument is null (Nothing in Visual Basic). public void OnCompleted(Action continuation) { QueueContinuation(continuation, flowContext: true); @@ -59,7 +59,7 @@ public void OnCompleted(Action continuation) /// Posts the back to the current context. /// The action to invoke asynchronously. - /// The argument is null (Nothing in Visual Basic). + /// The argument is null (Nothing in Visual Basic). public void UnsafeOnCompleted(Action continuation) { QueueContinuation(continuation, flowContext: false); @@ -68,7 +68,7 @@ public void UnsafeOnCompleted(Action continuation) /// Posts the back to the current context. /// The action to invoke asynchronously. /// true to flow ExecutionContext; false if flowing is not required. - /// The argument is null (Nothing in Visual Basic). + /// The argument is null (Nothing in Visual Basic). private static void QueueContinuation(Action continuation, bool flowContext) { ArgumentNullException.ThrowIfNull(continuation); diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/COMException.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/COMException.cs index f4dd72a3136175..86e0b7b7f303fa 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/COMException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/COMException.cs @@ -3,8 +3,8 @@ using System.ComponentModel; using System.Runtime.Serialization; -using System.Globalization; using System.Text; +using System.Runtime.CompilerServices; namespace System.Runtime.InteropServices { @@ -14,7 +14,7 @@ namespace System.Runtime.InteropServices /// recognize the HResult. /// [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class COMException : ExternalException { public COMException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs index 08769a6ab32fd0..a6335019d099f8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs @@ -108,10 +108,10 @@ public partial struct ComInterfaceDispatch /// pointer containing memory for all COM interface entries. /// /// All memory returned from this function must either be unmanaged memory, pinned managed memory, or have been - /// allocated with the API. + /// allocated with the API. /// /// If the interface entries cannot be created and a negative or null and a non-zero are returned, - /// the call to will throw a . + /// the call to will throw a . /// protected abstract unsafe ComInterfaceEntry* ComputeVtables(object obj, CreateComInterfaceFlags flags, out int count); @@ -122,7 +122,7 @@ public partial struct ComInterfaceDispatch /// Flags used to describe the external object. /// Returns a managed object associated with the supplied external COM object. /// - /// If the object cannot be created and null is returned, the call to will throw a . + /// If the object cannot be created and null is returned, the call to will throw a . /// protected abstract object? CreateObject(IntPtr externalComObject, CreateObjectFlags flags); diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ExternalException.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ExternalException.cs index 9032dbd17dc021..0c08ee31fe9c60 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ExternalException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ExternalException.cs @@ -12,7 +12,7 @@ =============================================================================*/ using System.ComponentModel; -using System.Globalization; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Runtime.InteropServices @@ -20,7 +20,7 @@ namespace System.Runtime.InteropServices // Base exception for COM Interop errors &; Structured Exception Handler // exceptions. [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class ExternalException : SystemException { public ExternalException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ICustomMarshaler.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ICustomMarshaler.cs index 4627e224b217ac..d0332168bfd266 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ICustomMarshaler.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ICustomMarshaler.cs @@ -1,6 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +#if MONO +using System.Diagnostics.CodeAnalysis; +#endif + namespace System.Runtime.InteropServices { // This the base interface that must be implemented by all custom marshalers. @@ -8,7 +12,7 @@ public interface ICustomMarshaler { #if MONO // ILLinker marks all methods of this type equally so the attribute can be on any of them - [System.Diagnostics.CodeAnalysis.DynamicDependency(nameof(Marshal.GetCustomMarshalerInstance), typeof(Marshal))] + [DynamicDependency(nameof(Marshal.GetCustomMarshalerInstance), typeof(Marshal))] #endif object MarshalNativeToManaged(IntPtr pNativeData); diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/IDynamicInterfaceCastable.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/IDynamicInterfaceCastable.cs index 014af67b0e07ea..e4b327da1cfee2 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/IDynamicInterfaceCastable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/IDynamicInterfaceCastable.cs @@ -26,7 +26,7 @@ public interface IDynamicInterfaceCastable /// /// If is false, this function should /// avoid throwing exceptions. If is - /// true and this function returns false, then + /// true and this function returns false, then /// will be thrown unless an exception is thrown by the implementation. /// bool IsInterfaceImplemented(RuntimeTypeHandle interfaceType, bool throwIfNotImplemented); @@ -43,7 +43,7 @@ public interface IDynamicInterfaceCastable /// /// The returned type must be an interface type and be marked with the /// . Otherwise, - /// will be thrown. + /// will be thrown. /// RuntimeTypeHandle GetInterfaceImplementation(RuntimeTypeHandle interfaceType); } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/InvalidComObjectException.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/InvalidComObjectException.cs index 45614c4f6f27dd..4090c2f25437b1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/InvalidComObjectException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/InvalidComObjectException.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Runtime.InteropServices @@ -12,7 +13,7 @@ namespace System.Runtime.InteropServices /// class factory. /// [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class InvalidComObjectException : SystemException { public InvalidComObjectException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/InvalidOleVariantTypeException.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/InvalidOleVariantTypeException.cs index 83b87e253ec09e..1f900d58a4397b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/InvalidOleVariantTypeException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/InvalidOleVariantTypeException.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Runtime.InteropServices @@ -11,7 +12,7 @@ namespace System.Runtime.InteropServices /// runtime is invalid. /// [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class InvalidOleVariantTypeException : SystemException { public InvalidOleVariantTypeException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.NoCom.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.NoCom.cs index 367bd323540546..8c7fb2e5ed09bb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.NoCom.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.NoCom.cs @@ -46,6 +46,7 @@ public static IntPtr CreateAggregatedObject(IntPtr pOuter, T o) where T : not [SupportedOSPlatform("windows")] [EditorBrowsable(EditorBrowsableState.Never)] + [return: NotNullIfNotNull(nameof(o))] public static object? CreateWrapperOfType(object? o, Type t) { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Windows.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Windows.cs index 4614f009e5b5e6..d826a438f3ec73 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Windows.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/Marshal.Windows.cs @@ -225,7 +225,7 @@ public static void FreeBSTR(IntPtr ptr) if (hr < 0) { if (throwOnError) - throw Marshal.GetExceptionForHR(hr, new IntPtr(-1))!; + throw GetExceptionForHR(hr, new IntPtr(-1))!; return null; } 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 14c91822eb25d4..692cdda484a440 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 @@ -480,7 +480,7 @@ public static void WriteIntPtr(IntPtr ptr, int ofs, IntPtr val) } [RequiresDynamicCode("Marshalling code for the object might not be available")] - [EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] + [EditorBrowsable(EditorBrowsableState.Never)] [Obsolete("WriteIntPtr(Object, Int32, IntPtr) may be unavailable in future releases.")] public static void WriteIntPtr(object ptr, int ofs, IntPtr val) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MarshalDirectiveException.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MarshalDirectiveException.cs index 8defddf208a10d..a5f4c45801f55c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MarshalDirectiveException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MarshalDirectiveException.cs @@ -11,12 +11,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Runtime.InteropServices { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class MarshalDirectiveException : SystemException { public MarshalDirectiveException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.cs index 952b0cfcc730b8..90ea2c99637675 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.cs @@ -22,10 +22,10 @@ public static partial class MemoryMarshal /// That type may not contain pointers or references. This is checked at runtime in order to preserve type safety. /// /// The source slice, of type . - /// + /// /// Thrown when contains pointers. /// - /// + /// /// Thrown if the Length property of the new Span would exceed int.MaxValue. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -45,10 +45,10 @@ ref Unsafe.As(ref GetReference(span)), /// That type may not contain pointers or references. This is checked at runtime in order to preserve type safety. /// /// The source slice, of type . - /// + /// /// Thrown when contains pointers. /// - /// + /// /// Thrown if the Length property of the new Span would exceed int.MaxValue. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -93,14 +93,14 @@ public static Memory AsMemory(ReadOnlyMemory memory) => /// for pinning but must never be dereferenced. This is useful for interop with methods that do not accept null pointers for zero-sized buffers. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static unsafe ref T GetNonNullPinnableReference(Span span) => ref (span.Length != 0) ? ref Unsafe.AsRef(in span._reference) : ref Unsafe.AsRef((void*)1); + internal static unsafe ref T GetNonNullPinnableReference(Span span) => ref (span.Length != 0) ? ref Unsafe.AsRef(in span._reference) : ref Unsafe.AsRef((void*)1); /// /// Returns a reference to the 0th element of the ReadOnlySpan. If the ReadOnlySpan is empty, returns a reference to fake non-null pointer. Such a reference /// can be used for pinning but must never be dereferenced. This is useful for interop with methods that do not accept null pointers for zero-sized buffers. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static unsafe ref T GetNonNullPinnableReference(ReadOnlySpan span) => ref (span.Length != 0) ? ref Unsafe.AsRef(in span._reference) : ref Unsafe.AsRef((void*)1); + internal static unsafe ref T GetNonNullPinnableReference(ReadOnlySpan span) => ref (span.Length != 0) ? ref Unsafe.AsRef(in span._reference) : ref Unsafe.AsRef((void*)1); #pragma warning restore IDE0060 // https://github.com/dotnet/roslyn-analyzers/issues/6228 /// @@ -111,7 +111,7 @@ public static Memory AsMemory(ReadOnlyMemory memory) => /// Supported only for platforms that support misaligned memory access or when the memory block is aligned by other means. /// /// The source slice, of type . - /// + /// /// Thrown when or contains pointers. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -166,7 +166,7 @@ ref Unsafe.As(ref span._reference), /// Supported only for platforms that support misaligned memory access or when the memory block is aligned by other means. /// /// The source slice, of type . - /// + /// /// Thrown when or contains pointers. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -209,7 +209,7 @@ public static ReadOnlySpan Cast(ReadOnlySpan span) } return new ReadOnlySpan( - ref Unsafe.As(ref MemoryMarshal.GetReference(span)), + ref Unsafe.As(ref GetReference(span)), toLength); } @@ -466,7 +466,7 @@ public static unsafe void Write(Span destination, ref T value) { ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length); } - Unsafe.WriteUnaligned(ref GetReference(destination), value); + Unsafe.WriteUnaligned(ref GetReference(destination), value); } /// @@ -485,7 +485,7 @@ public static unsafe bool TryWrite(Span destination, ref T value) { return false; } - Unsafe.WriteUnaligned(ref GetReference(destination), value); + Unsafe.WriteUnaligned(ref GetReference(destination), value); return true; } @@ -544,8 +544,8 @@ public static unsafe ref readonly T AsRef(ReadOnlySpan span) /// that array should not be unpinned while the returned Memory is still in use. /// Calling this method on an unpinned array could result in memory corruption. /// Returns default when is null. - /// Thrown when is covariant and array's type is not exactly T[]. - /// + /// 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 >=Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] 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 7987c7eb89f159..e5645feb21ffa6 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 @@ -765,7 +765,7 @@ public static bool TryParse(ReadOnlySpan s, NumberStyles style, IFormatPro /// /// /// - /// is not a . + /// is not a . public int CompareTo(object? obj) { if (obj is NFloat other) @@ -1375,21 +1375,21 @@ public static NFloat CreateTruncating(TOther value) [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out NFloat result) { - return TryConvertFrom(value, out result); + return TryConvertFrom(value, out result); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromSaturating(TOther value, out NFloat result) { - return TryConvertFrom(value, out result); + return TryConvertFrom(value, out result); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromTruncating(TOther value, out NFloat result) { - return TryConvertFrom(value, out result); + return TryConvertFrom(value, out result); } private static bool TryConvertFrom(TOther value, out NFloat result) @@ -1621,14 +1621,14 @@ static bool INumberBase.TryConvertToChecked(NFloat value, [Maybe [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertToSaturating(NFloat value, [MaybeNullWhen(false)] out TOther result) { - return TryConvertTo(value, out result); + return TryConvertTo(value, out result); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertToTruncating(NFloat value, [MaybeNullWhen(false)] out TOther result) { - return TryConvertTo(value, out result); + return TryConvertTo(value, out result); } private static bool TryConvertTo(NFloat value, [MaybeNullWhen(false)] out TOther result) diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs index f1b0f576bfb3f5..9a81662c0305f8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/NativeLibrary.cs @@ -34,9 +34,9 @@ public static partial class NativeLibrary /// /// The name of the native library to be loaded. /// The handle for the loaded native library. - /// If libraryPath is null - /// If the library can't be found. - /// If the library is not valid. + /// If libraryPath is null + /// If the library can't be found. + /// If the library is not valid. public static IntPtr Load(string libraryPath) { ArgumentNullException.ThrowIfNull(libraryPath); @@ -50,7 +50,7 @@ public static IntPtr Load(string libraryPath) /// The name of the native library to be loaded. /// The out-parameter for the loaded native library handle. /// True on successful load, false otherwise. - /// If libraryPath is null + /// If libraryPath is null public static bool TryLoad(string libraryPath, out IntPtr handle) { ArgumentNullException.ThrowIfNull(libraryPath); @@ -77,10 +77,10 @@ public static bool TryLoad(string libraryPath, out IntPtr handle) /// The assembly loading the native library. /// The search path. /// The handle for the loaded library. - /// If libraryPath or assembly is null - /// If assembly is not a RuntimeAssembly - /// If the library can't be found. - /// If the library is not valid. + /// If libraryPath or assembly is null + /// If assembly is not a RuntimeAssembly + /// If the library can't be found. + /// If the library is not valid. public static IntPtr Load(string libraryName, Assembly assembly, DllImportSearchPath? searchPath) { ArgumentNullException.ThrowIfNull(libraryName); @@ -114,8 +114,8 @@ public static IntPtr Load(string libraryName, Assembly assembly, DllImportSearch /// The search path. /// The out-parameter for the loaded native library handle. /// True on successful load, false otherwise. - /// If libraryPath or assembly is null - /// If assembly is not a RuntimeAssembly + /// If libraryPath or assembly is null + /// If assembly is not a RuntimeAssembly public static bool TryLoad(string libraryName, Assembly assembly, DllImportSearchPath? searchPath, out IntPtr handle) { ArgumentNullException.ThrowIfNull(libraryName); @@ -151,8 +151,8 @@ public static void Free(IntPtr handle) /// The native library handle. /// The name of the exported symbol. /// The address of the symbol. - /// If handle or name is null - /// If the symbol is not found + /// If handle or name is null + /// If the symbol is not found public static IntPtr GetExport(IntPtr handle, string name) { ArgumentNullException.ThrowIfNull(handle); @@ -168,7 +168,7 @@ public static IntPtr GetExport(IntPtr handle, string name) /// The name of the exported symbol. /// The out-parameter for the symbol address, if it exists. /// True on success, false otherwise. - /// If handle or name is null + /// If handle or name is null public static bool TryGetExport(IntPtr handle, string name, out IntPtr address) { ArgumentNullException.ThrowIfNull(handle); @@ -196,8 +196,8 @@ public static bool TryGetExport(IntPtr handle, string name, out IntPtr address) /// /// The assembly for which the resolver is registered. /// The resolver callback to register. - /// If assembly or resolver is null - /// If a resolver is already set for this assembly + /// If assembly or resolver is null + /// If a resolver is already set for this assembly public static void SetDllImportResolver(Assembly assembly, DllImportResolver resolver) { ArgumentNullException.ThrowIfNull(assembly); diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveC/ObjectiveCTrackedTypeAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveC/ObjectiveCTrackedTypeAttribute.cs index 20c51d6f189cf9..28092040358f60 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveC/ObjectiveCTrackedTypeAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ObjectiveC/ObjectiveCTrackedTypeAttribute.cs @@ -8,7 +8,7 @@ namespace System.Runtime.InteropServices.ObjectiveC /// /// Attribute used to indicate a class represents a tracked Objective-C type. /// - [System.Runtime.Versioning.SupportedOSPlatformAttribute("macos")] + [SupportedOSPlatform("macos")] [AttributeUsage(AttributeTargets.Class, Inherited = true, AllowMultiple = false)] public sealed class ObjectiveCTrackedTypeAttribute : Attribute { diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/SEHException.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/SEHException.cs index 7b3596354d1a0a..aa71ebfb3110ba 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/SEHException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/SEHException.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Runtime.InteropServices @@ -10,7 +11,7 @@ namespace System.Runtime.InteropServices /// Exception for Structured Exception Handler exceptions. /// [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class SEHException : ExternalException { public SEHException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/SafeArrayRankMismatchException.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/SafeArrayRankMismatchException.cs index f61cd68137f512..37e1a657931c1f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/SafeArrayRankMismatchException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/SafeArrayRankMismatchException.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Runtime.InteropServices @@ -11,7 +12,7 @@ namespace System.Runtime.InteropServices /// than the array rank specified in the metadata. /// [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class SafeArrayRankMismatchException : SystemException { public SafeArrayRankMismatchException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/SafeArrayTypeMismatchException.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/SafeArrayTypeMismatchException.cs index 6f27786022ee59..4211cc93e6aed5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/SafeArrayTypeMismatchException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/SafeArrayTypeMismatchException.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Runtime.InteropServices @@ -11,7 +12,7 @@ namespace System.Runtime.InteropServices /// than the safe array sub type specified in the metadata. /// [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class SafeArrayTypeMismatchException : SystemException { public SafeArrayTypeMismatchException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/SuppressGCTransitionAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/SuppressGCTransitionAttribute.cs index 4c3c2d72e868ad..b41d10ee520e94 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/SuppressGCTransitionAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/SuppressGCTransitionAttribute.cs @@ -26,7 +26,7 @@ namespace System.Runtime.InteropServices /// /// /// - /// This attribute is ignored if applied to a method without the . + /// This attribute is ignored if applied to a method without the . /// /// Forgoing this transition can yield benefits when the cost of the transition is more than the execution time /// of the unmanaged function. However, avoiding this transition removes some of the guarantees the runtime diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/UnmanagedCallersOnlyAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/UnmanagedCallersOnlyAttribute.cs index 05efcee15074fd..411260e321d795 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/UnmanagedCallersOnlyAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/UnmanagedCallersOnlyAttribute.cs @@ -4,7 +4,7 @@ namespace System.Runtime.InteropServices { /// - /// Any method marked with can be directly called from + /// Any method marked with can be directly called from /// native code. The function token can be loaded to a local variable using the address-of operator /// in C# and passed as a callback to a native method. /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/UnmanagedType.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/UnmanagedType.cs index cc528f16a0da19..6ddf12deda151e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/UnmanagedType.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/UnmanagedType.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.ComponentModel; + namespace System.Runtime.InteropServices { public enum UnmanagedType @@ -16,8 +18,8 @@ public enum UnmanagedType U8 = 0xa, // 8 byte unsigned value R4 = 0xb, // 4 byte floating point R8 = 0xc, // 8 byte floating point - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - [System.ObsoleteAttribute("Marshalling as Currency may be unavailable in future releases.")] + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Marshalling as Currency may be unavailable in future releases.")] Currency = 0xf, // A currency BStr = 0x13, // OLE Unicode BSTR LPStr = 0x14, // Ptr to SBCS string @@ -25,30 +27,30 @@ public enum UnmanagedType LPTStr = 0x16, // Ptr to OS preferred (SBCS/Unicode) string ByValTStr = 0x17, // OS preferred (SBCS/Unicode) inline string (only valid in structs) IUnknown = 0x19, // COM IUnknown pointer. - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [EditorBrowsable(EditorBrowsableState.Never)] IDispatch = 0x1a, // COM IDispatch pointer - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [EditorBrowsable(EditorBrowsableState.Never)] Struct = 0x1b, // Structure Interface = 0x1c, // COM interface - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [EditorBrowsable(EditorBrowsableState.Never)] SafeArray = 0x1d, // OLE SafeArray ByValArray = 0x1e, // Array of fixed size (only valid in structs) SysInt = 0x1f, // Hardware natural sized signed integer SysUInt = 0x20, - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - [System.ObsoleteAttribute("Marshalling as VBByRefString may be unavailable in future releases.")] + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Marshalling as VBByRefString may be unavailable in future releases.")] VBByRefStr = 0x22, - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - [System.ObsoleteAttribute("Marshalling as AnsiBStr may be unavailable in future releases.")] + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Marshalling as AnsiBStr may be unavailable in future releases.")] AnsiBStr = 0x23, // OLE BSTR containing SBCS characters - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - [System.ObsoleteAttribute("Marshalling as TBstr may be unavailable in future releases.")] + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Marshalling as TBstr may be unavailable in future releases.")] TBStr = 0x24, // Ptr to OS preferred (SBCS/Unicode) BSTR - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + [EditorBrowsable(EditorBrowsableState.Never)] VariantBool = 0x25, // OLE defined BOOLEAN (2 bytes, true == -1, false == 0) FunctionPtr = 0x26, // Function pointer - [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] - [System.ObsoleteAttribute("Marshalling arbitrary types may be unavailable in future releases. Specify the type you wish to marshal as.")] + [EditorBrowsable(EditorBrowsableState.Never)] + [Obsolete("Marshalling arbitrary types may be unavailable in future releases. Specify the type you wish to marshal as.")] AsAny = 0x28, // Paired with Object type and does runtime marshalling determination LPArray = 0x2a, // C style array LPStruct = 0x2b, // Pointer to a structure 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 15285f8c9a2bbd..48e3cc07f98310 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 @@ -558,11 +558,11 @@ public static unsafe Vector128 ConvertToSingle(Vector128 vector) if (Fma.IsSupported) { - return Fma.MultiplyAdd(upper, Vector128.Create(65536.0f), lower); + return Fma.MultiplyAdd(upper, Create(65536.0f), lower); } else { - Vector128 result = Sse.Multiply(upper, Vector128.Create(65536.0f)); + Vector128 result = Sse.Multiply(upper, Create(65536.0f)); return Sse.Add(result, lower); } } @@ -2737,7 +2737,7 @@ internal static void StoreLowerUnsafe(this Vector128 source, ref T destina where T : struct { ref byte address = ref Unsafe.As(ref Unsafe.Add(ref destination, elementOffset)); - Unsafe.WriteUnaligned(ref address, source.AsDouble().ToScalar()); + Unsafe.WriteUnaligned(ref address, source.AsDouble().ToScalar()); } /// Stores a vector at the given destination. 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 5854024ceb1c6b..fe174c3ab430e1 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 @@ -473,11 +473,11 @@ public static Vector256 ConvertToSingle(Vector256 vector) if (Fma.IsSupported) { - return Fma.MultiplyAdd(upper, Vector256.Create(65536.0f), lower); + return Fma.MultiplyAdd(upper, Create(65536.0f), lower); } else { - Vector256 result = Avx.Multiply(upper, Vector256.Create(65536.0f)); + Vector256 result = Avx.Multiply(upper, Create(65536.0f)); return Avx.Add(result, lower); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.cs index a4cbb1db458bd3..0cde7057ff8f84 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Intrinsics/X86/X86Base.cs @@ -32,7 +32,7 @@ internal X64() { } /// /// /// This method is to remain internal. - /// Its functionality is exposed in the public class. + /// Its functionality is exposed in the public class. /// internal static ulong BitScanForward(ulong value) => BitScanForward(value); @@ -43,7 +43,7 @@ internal X64() { } /// /// /// This method is to remain internal. - /// Its functionality is exposed in the public class. + /// Its functionality is exposed in the public class. /// internal static ulong BitScanReverse(ulong value) => BitScanReverse(value); @@ -69,7 +69,7 @@ internal X64() { } /// /// /// This method is to remain internal. - /// Its functionality is exposed in the public class. + /// Its functionality is exposed in the public class. /// internal static uint BitScanForward(uint value) => BitScanForward(value); @@ -80,7 +80,7 @@ internal X64() { } /// /// /// This method is to remain internal. - /// Its functionality is exposed in the public class. + /// Its functionality is exposed in the public class. /// internal static uint BitScanReverse(uint value) => BitScanReverse(value); 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 d7ba398a03f45b..b8b4ba086ad69b 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 @@ -8,6 +8,7 @@ using System.IO; using System.Reflection; using System.Runtime.InteropServices; +using System.Security; using System.Threading; namespace System.Runtime.Loader @@ -309,7 +310,7 @@ public static AssemblyName GetAssemblyName(string assemblyPath) } #if !NATIVEAOT - [System.Security.DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod + [DynamicSecurityMethod] // Methods containing StackCrawlMark local var has to be marked DynamicSecurityMethod public Assembly LoadFromAssemblyName(AssemblyName assemblyName) { ArgumentNullException.ThrowIfNull(assemblyName); @@ -495,10 +496,10 @@ private void VerifyIsAlive() /// This is an advanced setting used in reflection assembly loading scenarios. /// /// There are a set of contextual reflection APIs which load managed assemblies through an inferred AssemblyLoadContext. - /// * - /// * - /// * - /// * + /// * + /// * + /// * + /// * /// /// When CurrentContextualReflectionContext is null, the AssemblyLoadContext is inferred. /// The inference logic is simple. @@ -508,7 +509,7 @@ private void VerifyIsAlive() /// When this property is set, the CurrentContextualReflectionContext value is used by these contextual reflection APIs for loading. /// /// This property is typically set in a using block by - /// . + /// . /// /// The property is stored in an AsyncLocal<AssemblyLoadContext>. This means the setting can be unique for every async or thread in the process. /// @@ -529,7 +530,7 @@ private static void SetCurrentContextualReflectionContext(AssemblyLoadContext? v /// A disposable ContextualReflectionScope for use in a using block /// /// Sets CurrentContextualReflectionContext to this instance. - /// + /// /// /// Returns a disposable ContextualReflectionScope for use in a using block. When the using calls the /// Dispose() method, it restores the ContextualReflectionScope to its previous value. @@ -544,7 +545,7 @@ public ContextualReflectionScope EnterContextualReflection() /// A disposable ContextualReflectionScope for use in a using block /// /// Sets CurrentContextualReflectionContext to the AssemblyLoadContext which loaded activating. - /// + /// /// /// Returns a disposable ContextualReflectionScope for use in a using block. When the using calls the /// Dispose() method, it restores the ContextualReflectionScope to its previous value. @@ -570,7 +571,7 @@ public static ContextualReflectionScope EnterContextualReflection(Assembly? acti /// This is an implementation detail of the AssemblyLoadContext.EnterContextualReflection APIs. /// It is a struct, to avoid heap allocation. /// It is required to be public to avoid boxing. - /// + /// /// [EditorBrowsable(EditorBrowsableState.Never)] public struct ContextualReflectionScope : IDisposable @@ -581,8 +582,8 @@ public struct ContextualReflectionScope : IDisposable internal ContextualReflectionScope(AssemblyLoadContext? activating) { - _predecessor = AssemblyLoadContext.CurrentContextualReflectionContext; - AssemblyLoadContext.SetCurrentContextualReflectionContext(activating); + _predecessor = CurrentContextualReflectionContext; + SetCurrentContextualReflectionContext(activating); _activated = activating; _initialized = true; } @@ -593,7 +594,7 @@ public void Dispose() { // Do not clear initialized. Always restore the _predecessor in Dispose() // _initialized = false; - AssemblyLoadContext.SetCurrentContextualReflectionContext(_predecessor); + SetCurrentContextualReflectionContext(_predecessor); } } } @@ -623,12 +624,12 @@ public void Dispose() { resolvedAssembly = handler(this, assemblyName); #if CORECLR - if (AssemblyLoadContext.IsTracingEnabled()) + if (IsTracingEnabled()) { - AssemblyLoadContext.TraceResolvingHandlerInvoked( + TraceResolvingHandlerInvoked( assemblyName.FullName, handler.Method.Name, - this != AssemblyLoadContext.Default ? ToString() : Name, + this != Default ? ToString() : Name, resolvedAssembly?.FullName, resolvedAssembly != null && !resolvedAssembly.IsDynamic ? resolvedAssembly.Location : null); } @@ -737,9 +738,9 @@ internal static void InvokeAssemblyLoadEvent(Assembly assembly) { Assembly? asm = handler(AppDomain.CurrentDomain, args); #if CORECLR - if (eventHandler == AssemblyResolve && AssemblyLoadContext.IsTracingEnabled()) + if (eventHandler == AssemblyResolve && IsTracingEnabled()) { - AssemblyLoadContext.TraceAssemblyResolveHandlerInvoked( + TraceAssemblyResolveHandlerInvoked( name, handler.Method.Name, asm?.FullName, @@ -781,24 +782,24 @@ internal static void InvokeAssemblyLoadEvent(Assembly assembly) string assemblyPath = Path.Combine(parentDirectory, assemblyName.CultureName!, $"{assemblyName.Name}.dll"); - bool exists = System.IO.FileSystem.FileExists(assemblyPath); + bool exists = FileSystem.FileExists(assemblyPath); if (!exists && PathInternal.IsCaseSensitive) { #if CORECLR - if (AssemblyLoadContext.IsTracingEnabled()) + if (IsTracingEnabled()) { - AssemblyLoadContext.TraceSatelliteSubdirectoryPathProbed(assemblyPath, HResults.COR_E_FILENOTFOUND); + TraceSatelliteSubdirectoryPathProbed(assemblyPath, HResults.COR_E_FILENOTFOUND); } #endif // CORECLR assemblyPath = Path.Combine(parentDirectory, assemblyName.CultureName!.ToLowerInvariant(), $"{assemblyName.Name}.dll"); - exists = System.IO.FileSystem.FileExists(assemblyPath); + exists = FileSystem.FileExists(assemblyPath); } Assembly? asm = exists ? parentALC.LoadFromAssemblyPath(assemblyPath) : null; #if CORECLR - if (AssemblyLoadContext.IsTracingEnabled()) + if (IsTracingEnabled()) { - AssemblyLoadContext.TraceSatelliteSubdirectoryPathProbed(assemblyPath, exists ? HResults.S_OK : HResults.COR_E_FILENOTFOUND); + TraceSatelliteSubdirectoryPathProbed(assemblyPath, exists ? HResults.S_OK : HResults.COR_E_FILENOTFOUND); } #endif // CORECLR diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/MemoryFailPoint.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/MemoryFailPoint.cs index 5c3cd273bba57b..3b2c6b93a7cd76 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/MemoryFailPoint.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/MemoryFailPoint.cs @@ -369,7 +369,7 @@ internal MemoryFailPointState(int allocationSizeInMB, ulong segmentSize, bool ne { _stackTrace = Environment.StackTrace; } - catch (System.Security.SecurityException) + catch (Security.SecurityException) { _stackTrace = "no permission"; } @@ -381,7 +381,7 @@ internal MemoryFailPointState(int allocationSizeInMB, ulong segmentSize, bool ne public override string ToString() { - return string.Format(System.Globalization.CultureInfo.InvariantCulture, "MemoryFailPoint detected insufficient memory to guarantee an operation could complete. Checked for {0} MB, for allocation size of {1} MB. Need page file? {2} Need Address Space? {3} Need Contiguous address space? {4} Avail page file: {5} MB Total free VA space: {6} MB Contiguous free address space (found): {7} MB Space reserved by process's MemoryFailPoints: {8} MB", + return string.Format(Globalization.CultureInfo.InvariantCulture, "MemoryFailPoint detected insufficient memory to guarantee an operation could complete. Checked for {0} MB, for allocation size of {1} MB. Need page file? {2} Need Address Space? {3} Need Contiguous address space? {4} Avail page file: {5} MB Total free VA space: {6} MB Contiguous free address space (found): {7} MB Space reserved by process's MemoryFailPoints: {8} MB", _segmentSize >> 20, _allocationSizeInMB, _needPageFile, _needAddressSpace, _needContiguousVASpace, _availPageFile >> 20, _totalFreeAddressSpace >> 20, diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Serialization/SerializationException.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Serialization/SerializationException.cs index 8b0ec24d125717..4831d57cd469eb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Serialization/SerializationException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Serialization/SerializationException.cs @@ -2,11 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; namespace System.Runtime.Serialization { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class SerializationException : SystemException { /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/PlatformAttributes.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/PlatformAttributes.cs index 06359cf91171b6..85fbeb604c669c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/PlatformAttributes.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/Versioning/PlatformAttributes.cs @@ -44,7 +44,7 @@ public TargetPlatformAttribute(string platformName) : base(platformName) /// applied to indicate support on multiple operating systems. /// /// - /// Callers can apply a + /// Callers can apply a /// or use guards to prevent calls to APIs on unsupported operating systems. /// /// A given platform should only be specified once. @@ -150,7 +150,7 @@ public ObsoletedOSPlatformAttribute(string platformName, string? message) : base /// Multiple attributes can be applied to indicate guard for multiple supported platforms. /// /// - /// Callers can apply a to a field, property or method + /// Callers can apply a to a field, property or method /// and use that field, property or method in a conditional or assert statements in order to safely call platform specific APIs. /// /// The type of the field or property should be boolean, the method return type should be boolean in order to be used as platform guard. @@ -176,7 +176,7 @@ public SupportedOSPlatformGuardAttribute(string platformName) : base(platformNam /// Multiple attributes can be applied to indicate guard for multiple unsupported platforms. /// /// - /// Callers can apply a to a field, property or method + /// Callers can apply a to a field, property or method /// and use that field, property or method in a conditional or assert statements as a guard to safely call APIs unsupported on those platforms. /// /// The type of the field or property should be boolean, the method return type should be boolean in order to be used as platform guard. diff --git a/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs b/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs index fcc1f0cfd30022..b7da6009495c24 100644 --- a/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs +++ b/src/libraries/System.Private.CoreLib/src/System/RuntimeType.cs @@ -185,7 +185,7 @@ protected override TypeCode GetTypeCodeImpl() if (typeCode != TypeCode.Empty) return typeCode; - typeCode = Type.GetRuntimeTypeCode(this); + typeCode = GetRuntimeTypeCode(this); Cache.TypeCode = typeCode; return typeCode; @@ -291,7 +291,7 @@ public override bool IsAssignableFrom([NotNullWhen(true)] Type? c) } // Special case for TypeBuilder to be backward-compatible. - if (c is System.Reflection.Emit.TypeBuilder) + if (c is Reflection.Emit.TypeBuilder) { // If c is a subclass of this class, then c can be cast to this type. if (c.IsSubclassOf(this)) diff --git a/src/libraries/System.Private.CoreLib/src/System/SByte.cs b/src/libraries/System.Private.CoreLib/src/System/SByte.cs index 9f09ec5318ad69..3b6441b1eb16bd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SByte.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SByte.cs @@ -308,7 +308,7 @@ static bool IBinaryInteger.TryReadBigEndian(ReadOnlySpan source, bo // We need to also track if the input data is unsigned isUnsigned |= (sign == 0); - if (isUnsigned && sbyte.IsNegative(sign)) + if (isUnsigned && IsNegative(sign)) { // When we are unsigned and the most significant bit is set, we are a large positive // and therefore definitely out of range @@ -328,7 +328,7 @@ static bool IBinaryInteger.TryReadBigEndian(ReadOnlySpan source, bo return false; } - if (isUnsigned == sbyte.IsNegative((sbyte)source[^sizeof(sbyte)])) + if (isUnsigned == IsNegative((sbyte)source[^sizeof(sbyte)])) { // When the most significant bit of the value being set/clear matches whether we are unsigned // or signed then we are a large positive/negative and therefore definitely out of range @@ -361,7 +361,7 @@ static bool IBinaryInteger.TryReadLittleEndian(ReadOnlySpan source, // We need to also track if the input data is unsigned isUnsigned |= (sign == 0); - if (isUnsigned && sbyte.IsNegative(sign)) + if (isUnsigned && IsNegative(sign)) { // When we are unsigned and the most significant bit is set, we are a large positive // and therefore definitely out of range @@ -381,7 +381,7 @@ static bool IBinaryInteger.TryReadLittleEndian(ReadOnlySpan source, return false; } - if (isUnsigned == sbyte.IsNegative((sbyte)source[sizeof(sbyte) - 1])) + if (isUnsigned == IsNegative((sbyte)source[sizeof(sbyte) - 1])) { // When the most significant bit of the value being set/clear matches whether we are unsigned // or signed then we are a large positive/negative and therefore definitely out of range diff --git a/src/libraries/System.Private.CoreLib/src/System/SR.cs b/src/libraries/System.Private.CoreLib/src/System/SR.cs index 148e91074e1bd1..a03a12876f71cf 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SR.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SR.cs @@ -67,7 +67,7 @@ private static string InternalGetResourceString(string key) #if SYSTEM_PRIVATE_CORELIB // Note: our infrastructure for reporting this exception will again cause resource lookup. // This is the most direct way of dealing with that problem. - string message = $@"Encountered infinite recursion while looking up resource '{key}' in {System.CoreLib.Name}. Verify the installation of .NET is complete and does not need repairing, and that the state of the process has not become corrupted."; + string message = $@"Encountered infinite recursion while looking up resource '{key}' in {CoreLib.Name}. Verify the installation of .NET is complete and does not need repairing, and that the state of the process has not become corrupted."; Environment.FailFast(message); #endif } 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 a61f9b7bd210c3..fc7b012821629a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticCharSearchValues.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticCharSearchValues.cs @@ -34,30 +34,16 @@ public ProbabilisticCharSearchValues(scoped ReadOnlySpan values) internal override bool ContainsCore(char value) => ProbabilisticMap.Contains(ref Unsafe.As(ref _map), _values, value); - [MethodImpl(MethodImplOptions.AggressiveInlining)] internal override int IndexOfAny(ReadOnlySpan span) => - IndexOfAny(ref MemoryMarshal.GetReference(span), span.Length); + ProbabilisticMap.IndexOfAny(ref Unsafe.As(ref _map), ref MemoryMarshal.GetReference(span), span.Length, _values); - [MethodImpl(MethodImplOptions.AggressiveInlining)] internal override int IndexOfAnyExcept(ReadOnlySpan span) => - IndexOfAny(ref MemoryMarshal.GetReference(span), span.Length); + ProbabilisticMap.IndexOfAnySimpleLoop(ref MemoryMarshal.GetReference(span), span.Length, _values); - [MethodImpl(MethodImplOptions.AggressiveInlining)] internal override int LastIndexOfAny(ReadOnlySpan span) => - LastIndexOfAny(ref MemoryMarshal.GetReference(span), span.Length); + ProbabilisticMap.LastIndexOfAny(ref Unsafe.As(ref _map), ref MemoryMarshal.GetReference(span), span.Length, _values); - [MethodImpl(MethodImplOptions.AggressiveInlining)] internal override int LastIndexOfAnyExcept(ReadOnlySpan span) => - LastIndexOfAny(ref MemoryMarshal.GetReference(span), span.Length); - - [MethodImpl(MethodImplOptions.NoInlining)] - private int IndexOfAny(ref char searchSpace, int searchSpaceLength) - where TNegator : struct, IndexOfAnyAsciiSearcher.INegator => - ProbabilisticMap.IndexOfAny(ref Unsafe.As(ref _map), ref searchSpace, searchSpaceLength, _values); - - [MethodImpl(MethodImplOptions.NoInlining)] - private int LastIndexOfAny(ref char searchSpace, int searchSpaceLength) - where TNegator : struct, IndexOfAnyAsciiSearcher.INegator => - ProbabilisticMap.LastIndexOfAny(ref Unsafe.As(ref _map), ref searchSpace, searchSpaceLength, _values); + ProbabilisticMap.LastIndexOfAnySimpleLoop(ref MemoryMarshal.GetReference(span), span.Length, _values); } } 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 564e65f4d0dc11..8a0d6532382f50 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticMap.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SearchValues/ProbabilisticMap.cs @@ -215,116 +215,96 @@ private static bool ShouldUseSimpleLoop(int searchSpaceLength, int valuesLength) || (searchSpaceLength < 20 && searchSpaceLength < (valuesLength >> 1)); } - public static int IndexOfAny(ref char searchSpace, int searchSpaceLength, ref char values, int valuesLength) => - IndexOfAny>(ref searchSpace, searchSpaceLength, ref values, valuesLength); - - public static int IndexOfAnyExcept(ref char searchSpace, int searchSpaceLength, ref char values, int valuesLength) => - IndexOfAny>(ref searchSpace, searchSpaceLength, ref values, valuesLength); - - public static int LastIndexOfAny(ref char searchSpace, int searchSpaceLength, ref char values, int valuesLength) => - LastIndexOfAny>(ref searchSpace, searchSpaceLength, ref values, valuesLength); - - public static int LastIndexOfAnyExcept(ref char searchSpace, int searchSpaceLength, ref char values, int valuesLength) => - LastIndexOfAny>(ref searchSpace, searchSpaceLength, ref values, valuesLength); - - private static int IndexOfAny(ref char searchSpace, int searchSpaceLength, ref char values, int valuesLength) - where TNegator : struct, SpanHelpers.INegator + public static int IndexOfAny(ref char searchSpace, int searchSpaceLength, ref char values, int valuesLength) { var valuesSpan = new ReadOnlySpan(ref values, valuesLength); // If the search space is relatively short compared to the needle, do a simple O(n * m) search. if (ShouldUseSimpleLoop(searchSpaceLength, valuesLength)) { - ref char searchSpaceEnd = ref Unsafe.Add(ref searchSpace, searchSpaceLength); - ref char cur = ref searchSpace; + return IndexOfAnySimpleLoop(ref searchSpace, searchSpaceLength, valuesSpan); + } - while (!Unsafe.AreSame(ref cur, ref searchSpaceEnd)) - { - char c = cur; - if (TNegator.NegateIfNeeded(Contains(valuesSpan, c))) - { - return (int)((nuint)Unsafe.ByteOffset(ref searchSpace, ref cur) / sizeof(char)); - } + if (IndexOfAnyAsciiSearcher.TryIndexOfAny(ref searchSpace, searchSpaceLength, valuesSpan, out int index)) + { + return index; + } - cur = ref Unsafe.Add(ref cur, 1); - } + return ProbabilisticIndexOfAny(ref searchSpace, searchSpaceLength, ref values, valuesLength); + } - return -1; - } + public static int IndexOfAnyExcept(ref char searchSpace, int searchSpaceLength, ref char values, int valuesLength) + { + var valuesSpan = new ReadOnlySpan(ref values, valuesLength); - if (typeof(TNegator) == typeof(SpanHelpers.DontNegate) - ? IndexOfAnyAsciiSearcher.TryIndexOfAny(ref searchSpace, searchSpaceLength, valuesSpan, out int index) - : IndexOfAnyAsciiSearcher.TryIndexOfAnyExcept(ref searchSpace, searchSpaceLength, valuesSpan, out index)) + if (IndexOfAnyAsciiSearcher.IsVectorizationSupported && + !ShouldUseSimpleLoop(searchSpaceLength, valuesLength) && + IndexOfAnyAsciiSearcher.TryIndexOfAnyExcept(ref searchSpace, searchSpaceLength, valuesSpan, out int index)) { return index; } - return ProbabilisticIndexOfAny(ref searchSpace, searchSpaceLength, ref values, valuesLength); + return IndexOfAnySimpleLoop(ref searchSpace, searchSpaceLength, valuesSpan); } - private static int LastIndexOfAny(ref char searchSpace, int searchSpaceLength, ref char values, int valuesLength) - where TNegator : struct, SpanHelpers.INegator + public static int LastIndexOfAny(ref char searchSpace, int searchSpaceLength, ref char values, int valuesLength) { var valuesSpan = new ReadOnlySpan(ref values, valuesLength); // If the search space is relatively short compared to the needle, do a simple O(n * m) search. if (ShouldUseSimpleLoop(searchSpaceLength, valuesLength)) { - for (int i = searchSpaceLength - 1; i >= 0; i--) - { - char c = Unsafe.Add(ref searchSpace, i); - if (TNegator.NegateIfNeeded(Contains(valuesSpan, c))) - { - return i; - } - } + return LastIndexOfAnySimpleLoop(ref searchSpace, searchSpaceLength, valuesSpan); + } - return -1; + if (IndexOfAnyAsciiSearcher.TryLastIndexOfAny(ref searchSpace, searchSpaceLength, valuesSpan, out int index)) + { + return index; } - if (typeof(TNegator) == typeof(SpanHelpers.DontNegate) - ? IndexOfAnyAsciiSearcher.TryLastIndexOfAny(ref searchSpace, searchSpaceLength, valuesSpan, out int index) - : IndexOfAnyAsciiSearcher.TryLastIndexOfAnyExcept(ref searchSpace, searchSpaceLength, valuesSpan, out index)) + return ProbabilisticLastIndexOfAny(ref searchSpace, searchSpaceLength, ref values, valuesLength); + } + + public static int LastIndexOfAnyExcept(ref char searchSpace, int searchSpaceLength, ref char values, int valuesLength) + { + var valuesSpan = new ReadOnlySpan(ref values, valuesLength); + + if (IndexOfAnyAsciiSearcher.IsVectorizationSupported && + !ShouldUseSimpleLoop(searchSpaceLength, valuesLength) && + IndexOfAnyAsciiSearcher.TryLastIndexOfAnyExcept(ref searchSpace, searchSpaceLength, valuesSpan, out int index)) { return index; } - return ProbabilisticLastIndexOfAny(ref searchSpace, searchSpaceLength, ref values, valuesLength); + return LastIndexOfAnySimpleLoop(ref searchSpace, searchSpaceLength, valuesSpan); } [MethodImpl(MethodImplOptions.NoInlining)] - private static int ProbabilisticIndexOfAny(ref char searchSpace, int searchSpaceLength, ref char values, int valuesLength) - where TNegator : struct, SpanHelpers.INegator + private static 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); - return typeof(TNegator) == typeof(SpanHelpers.DontNegate) - ? IndexOfAny(ref charMap, ref searchSpace, searchSpaceLength, valuesSpan) - : IndexOfAny(ref charMap, ref searchSpace, searchSpaceLength, valuesSpan); + return IndexOfAny(ref charMap, ref searchSpace, searchSpaceLength, valuesSpan); } [MethodImpl(MethodImplOptions.NoInlining)] - private static int ProbabilisticLastIndexOfAny(ref char searchSpace, int searchSpaceLength, ref char values, int valuesLength) - where TNegator : struct, SpanHelpers.INegator + private static 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); - return typeof(TNegator) == typeof(SpanHelpers.DontNegate) - ? LastIndexOfAny(ref charMap, ref searchSpace, searchSpaceLength, valuesSpan) - : LastIndexOfAny(ref charMap, ref searchSpace, searchSpaceLength, valuesSpan); + return LastIndexOfAny(ref charMap, ref searchSpace, searchSpaceLength, valuesSpan); } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static int IndexOfAny(ref uint charMap, ref char searchSpace, int searchSpaceLength, ReadOnlySpan values) - where TNegator : struct, IndexOfAnyAsciiSearcher.INegator + internal static int IndexOfAny(ref uint charMap, ref char searchSpace, int searchSpaceLength, ReadOnlySpan values) { - if ((Sse41.IsSupported || AdvSimd.Arm64.IsSupported) && typeof(TNegator) == typeof(IndexOfAnyAsciiSearcher.DontNegate) && searchSpaceLength >= 16) + if ((Sse41.IsSupported || AdvSimd.Arm64.IsSupported) && searchSpaceLength >= 16) { return IndexOfAnyVectorized(ref charMap, ref searchSpace, searchSpaceLength, values); } @@ -335,7 +315,7 @@ internal static int IndexOfAny(ref uint charMap, ref char searchSpace, while (!Unsafe.AreSame(ref cur, ref searchSpaceEnd)) { int ch = cur; - if (TNegator.NegateIfNeeded(Contains(ref charMap, values, ch))) + if (Contains(ref charMap, values, ch)) { return (int)((nuint)Unsafe.ByteOffset(ref searchSpace, ref cur) / sizeof(char)); } @@ -347,13 +327,12 @@ internal static int IndexOfAny(ref uint charMap, ref char searchSpace, } [MethodImpl(MethodImplOptions.AggressiveInlining)] - internal static int LastIndexOfAny(ref uint charMap, ref char searchSpace, int searchSpaceLength, ReadOnlySpan values) - where TNegator : struct, IndexOfAnyAsciiSearcher.INegator + internal static int LastIndexOfAny(ref uint charMap, ref char searchSpace, int searchSpaceLength, ReadOnlySpan values) { for (int i = searchSpaceLength - 1; i >= 0; i--) { int ch = Unsafe.Add(ref searchSpace, i); - if (TNegator.NegateIfNeeded(Contains(ref charMap, values, ch))) + if (Contains(ref charMap, values, ch)) { return i; } @@ -473,5 +452,42 @@ private static int IndexOfAnyVectorized(ref uint charMap, ref char searchSpace, return -1; } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int IndexOfAnySimpleLoop(ref char searchSpace, int searchSpaceLength, ReadOnlySpan values) + 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(Contains(values, c))) + { + return (int)((nuint)Unsafe.ByteOffset(ref searchSpace, ref cur) / sizeof(char)); + } + + cur = ref Unsafe.Add(ref cur, 1); + } + + return -1; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static int LastIndexOfAnySimpleLoop(ref char searchSpace, int searchSpaceLength, ReadOnlySpan values) + where TNegator : struct, IndexOfAnyAsciiSearcher.INegator + { + for (int i = searchSpaceLength - 1; i >= 0; i--) + { + char c = Unsafe.Add(ref searchSpace, i); + if (TNegator.NegateIfNeeded(Contains(values, c))) + { + return i; + } + } + + return -1; + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Security/CryptographicException.cs b/src/libraries/System.Private.CoreLib/src/System/Security/CryptographicException.cs index e9669d4aae2a15..6c8eab8a896f4d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Security/CryptographicException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Security/CryptographicException.cs @@ -3,12 +3,13 @@ using System.ComponentModel; using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Security.Cryptography { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class CryptographicException : SystemException { public CryptographicException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Security/SecurityException.cs b/src/libraries/System.Private.CoreLib/src/System/Security/SecurityException.cs index 42d95825ad6e92..786348af0329a9 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Security/SecurityException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Security/SecurityException.cs @@ -3,12 +3,13 @@ using System.ComponentModel; using System.Reflection; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Security { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class SecurityException : SystemException { private const string DemandedName = "Demanded"; diff --git a/src/libraries/System.Private.CoreLib/src/System/Security/VerificationException.cs b/src/libraries/System.Private.CoreLib/src/System/Security/VerificationException.cs index 604d29e2bad3de..d91ce07a341e3b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Security/VerificationException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Security/VerificationException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Security { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class VerificationException : SystemException { public VerificationException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Single.cs b/src/libraries/System.Private.CoreLib/src/System/Single.cs index 188534808e3a73..42d63de43279b7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Single.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Single.cs @@ -195,7 +195,7 @@ public static unsafe bool IsNegative(float f) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe bool IsNegativeInfinity(float f) { - return f == float.NegativeInfinity; + return f == NegativeInfinity; } /// Determines whether the specified value is normal. @@ -213,7 +213,7 @@ public static unsafe bool IsNormal(float f) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static unsafe bool IsPositiveInfinity(float f) { - return f == float.PositiveInfinity; + return f == PositiveInfinity; } /// Determines whether the specified value is subnormal. @@ -1147,21 +1147,21 @@ public static float MinMagnitudeNumber(float x, float y) [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromChecked(TOther value, out float result) { - return TryConvertFrom(value, out result); + return TryConvertFrom(value, out result); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromSaturating(TOther value, out float result) { - return TryConvertFrom(value, out result); + return TryConvertFrom(value, out result); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertFromTruncating(TOther value, out float result) { - return TryConvertFrom(value, out result); + return TryConvertFrom(value, out result); } private static bool TryConvertFrom(TOther value, out float result) @@ -1303,14 +1303,14 @@ static bool INumberBase.TryConvertToChecked(float value, [MaybeNu [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertToSaturating(float value, [MaybeNullWhen(false)] out TOther result) { - return TryConvertTo(value, out result); + return TryConvertTo(value, out result); } /// [MethodImpl(MethodImplOptions.AggressiveInlining)] static bool INumberBase.TryConvertToTruncating(float value, [MaybeNullWhen(false)] out TOther result) { - return TryConvertTo(value, out result); + return TryConvertTo(value, out result); } private static bool TryConvertTo(float value, [MaybeNullWhen(false)] out TOther result) diff --git a/src/libraries/System.Private.CoreLib/src/System/Span.cs b/src/libraries/System.Private.CoreLib/src/System/Span.cs index 26e32ffb4cfd08..b1ba7e9c6b80e5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Span.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Span.cs @@ -36,7 +36,7 @@ public readonly ref struct Span /// /// The target array. /// Returns default when is null. - /// Thrown when is covariant and array's type is not exactly T[]. + /// Thrown when is covariant and array's type is not exactly T[]. [MethodImpl(MethodImplOptions.AggressiveInlining)] public Span(T[]? array) { @@ -60,8 +60,8 @@ public Span(T[]? array) /// The index at which to begin the span. /// The number of items in the span. /// Returns default when is null. - /// Thrown when is covariant and array's type is not exactly T[]. - /// + /// 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 >Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -97,10 +97,10 @@ public Span(T[]? array, int start, int length) /// /// An unmanaged pointer to memory. /// The number of elements the memory contains. - /// + /// /// Thrown when is reference type or contains pointers and hence cannot be stored in unmanaged memory. /// - /// + /// /// Thrown when the specified is negative. /// [CLSCompliant(false)] @@ -142,7 +142,7 @@ internal Span(ref T reference, int length) /// /// /// - /// + /// /// Thrown when index less than 0 or index greater than or equal to Length /// public ref T this[int index] @@ -187,7 +187,7 @@ public bool IsEmpty /// /// This method is not supported as spans cannot be boxed. To compare two spans, use operator==. /// - /// + /// /// Always thrown by this method. /// [Obsolete("Equals() on Span will always throw an exception. Use the equality operator instead.")] @@ -198,7 +198,7 @@ public override bool Equals(object? obj) => /// /// This method is not supported as spans cannot be boxed. /// - /// + /// /// Always thrown by this method. /// [Obsolete("GetHashCode() on Span will always throw an exception.")] @@ -320,7 +320,7 @@ public unsafe void Fill(T value) /// a temporary location before the destination is overwritten. /// /// The span to copy items into. - /// + /// /// Thrown when the destination Span is shorter than the source Span. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -365,7 +365,7 @@ public bool TryCopyTo(Span destination) /// public static bool operator ==(Span left, Span right) => left._length == right._length && - Unsafe.AreSame(ref left._reference, ref right._reference); + Unsafe.AreSame(ref left._reference, ref right._reference); /// /// Defines an implicit conversion of a to a @@ -390,7 +390,7 @@ public override string ToString() /// Forms a slice out of the given span, beginning at 'start'. /// /// The index at which to begin this slice. - /// + /// /// Thrown when the specified index is not in range (<0 or >Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -407,7 +407,7 @@ public Span Slice(int start) /// /// The index at which to begin this slice. /// The desired length for the slice (exclusive). - /// + /// /// Thrown when the specified or end index is not in range (<0 or >Length). /// [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Byte.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Byte.cs index 39e9daa4724322..6681c5ff6bd023 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Byte.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.Byte.cs @@ -261,16 +261,16 @@ ref Unsafe.Add(ref searchSpace, relativeIndex + 1), do { // unlike IndexOf, here we use LZCNT to process matches starting from the end - int bitPos = 31 - BitOperations.LeadingZeroCount(mask); + int highestSetBitIndex = 31 - BitOperations.LeadingZeroCount(mask); if (valueLength == 2 || // we already matched two bytes SequenceEqual( - ref Unsafe.Add(ref searchSpace, offset + bitPos), + ref Unsafe.Add(ref searchSpace, offset + highestSetBitIndex), ref value, (nuint)(uint)valueLength)) // The (nuint)-cast is necessary to pick the correct overload { - return bitPos + offset; + return highestSetBitIndex + offset; } // Clear the highest set bit. - mask = BitOperations.ResetBit(mask, bitPos); + mask = BitOperations.FlipBit(mask, highestSetBitIndex); } while (mask != 0); } @@ -310,16 +310,16 @@ ref Unsafe.Add(ref searchSpace, offset + bitPos), do { // unlike IndexOf, here we use LZCNT to process matches starting from the end - int bitPos = 31 - BitOperations.LeadingZeroCount(mask); + int highestSetBitIndex = 31 - BitOperations.LeadingZeroCount(mask); if (valueLength == 2 || // we already matched two bytes SequenceEqual( - ref Unsafe.Add(ref searchSpace, offset + bitPos), + ref Unsafe.Add(ref searchSpace, offset + highestSetBitIndex), ref value, (nuint)(uint)valueLength)) // The (nuint)-cast is necessary to pick the correct overload { - return bitPos + offset; + return highestSetBitIndex + offset; } // Clear the highest set bit. - mask = BitOperations.ResetBit(mask, bitPos); + mask = BitOperations.FlipBit(mask, highestSetBitIndex); } while (mask != 0); } diff --git a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.cs b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.cs index 6f5ceb011ca6ca..8cff9345627f26 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SpanHelpers.cs @@ -42,30 +42,30 @@ public static unsafe void ClearWithoutReferences(ref byte b, nuint byteLength) return; case 3: Unsafe.As(ref b) = 0; - Unsafe.Add(ref b, 2) = 0; + Unsafe.Add(ref b, 2) = 0; return; case 4: Unsafe.As(ref b) = 0; return; case 5: Unsafe.As(ref b) = 0; - Unsafe.Add(ref b, 4) = 0; + Unsafe.Add(ref b, 4) = 0; return; case 6: Unsafe.As(ref b) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; return; case 7: Unsafe.As(ref b) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; - Unsafe.Add(ref b, 6) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; + Unsafe.Add(ref b, 6) = 0; return; case 8: #if TARGET_64BIT Unsafe.As(ref b) = 0; #else Unsafe.As(ref b) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; #endif return; case 9: @@ -73,68 +73,68 @@ public static unsafe void ClearWithoutReferences(ref byte b, nuint byteLength) Unsafe.As(ref b) = 0; #else Unsafe.As(ref b) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; #endif - Unsafe.Add(ref b, 8) = 0; + Unsafe.Add(ref b, 8) = 0; return; case 10: #if TARGET_64BIT Unsafe.As(ref b) = 0; #else Unsafe.As(ref b) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; #endif - Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; return; case 11: #if TARGET_64BIT Unsafe.As(ref b) = 0; #else Unsafe.As(ref b) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; #endif - Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; - Unsafe.Add(ref b, 10) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; + Unsafe.Add(ref b, 10) = 0; return; case 12: #if TARGET_64BIT Unsafe.As(ref b) = 0; #else Unsafe.As(ref b) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; #endif - Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; return; case 13: #if TARGET_64BIT Unsafe.As(ref b) = 0; #else Unsafe.As(ref b) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; #endif - Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; - Unsafe.Add(ref b, 12) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; + Unsafe.Add(ref b, 12) = 0; return; case 14: #if TARGET_64BIT Unsafe.As(ref b) = 0; #else Unsafe.As(ref b) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; #endif - Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 12)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 12)) = 0; return; case 15: #if TARGET_64BIT Unsafe.As(ref b) = 0; #else Unsafe.As(ref b) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; #endif - Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 12)) = 0; - Unsafe.Add(ref b, 14) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 12)) = 0; + Unsafe.Add(ref b, 14) = 0; return; case 16: #if TARGET_64BIT @@ -142,9 +142,9 @@ public static unsafe void ClearWithoutReferences(ref byte b, nuint byteLength) Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; #else Unsafe.As(ref b) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 12)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 12)) = 0; #endif return; case 17: @@ -153,11 +153,11 @@ public static unsafe void ClearWithoutReferences(ref byte b, nuint byteLength) Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; #else Unsafe.As(ref b) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 12)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 12)) = 0; #endif - Unsafe.Add(ref b, 16) = 0; + Unsafe.Add(ref b, 16) = 0; return; case 18: #if TARGET_64BIT @@ -165,11 +165,11 @@ public static unsafe void ClearWithoutReferences(ref byte b, nuint byteLength) Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; #else Unsafe.As(ref b) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 12)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 12)) = 0; #endif - Unsafe.As(ref Unsafe.Add(ref b, 16)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 16)) = 0; return; case 19: #if TARGET_64BIT @@ -177,12 +177,12 @@ public static unsafe void ClearWithoutReferences(ref byte b, nuint byteLength) Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; #else Unsafe.As(ref b) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 12)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 12)) = 0; #endif - Unsafe.As(ref Unsafe.Add(ref b, 16)) = 0; - Unsafe.Add(ref b, 18) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 16)) = 0; + Unsafe.Add(ref b, 18) = 0; return; case 20: #if TARGET_64BIT @@ -190,11 +190,11 @@ public static unsafe void ClearWithoutReferences(ref byte b, nuint byteLength) Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; #else Unsafe.As(ref b) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 12)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 12)) = 0; #endif - Unsafe.As(ref Unsafe.Add(ref b, 16)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 16)) = 0; return; case 21: #if TARGET_64BIT @@ -202,12 +202,12 @@ public static unsafe void ClearWithoutReferences(ref byte b, nuint byteLength) Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; #else Unsafe.As(ref b) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 12)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 12)) = 0; #endif - Unsafe.As(ref Unsafe.Add(ref b, 16)) = 0; - Unsafe.Add(ref b, 20) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 16)) = 0; + Unsafe.Add(ref b, 20) = 0; return; case 22: #if TARGET_64BIT @@ -215,12 +215,12 @@ public static unsafe void ClearWithoutReferences(ref byte b, nuint byteLength) Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; #else Unsafe.As(ref b) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 12)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 4)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 8)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 12)) = 0; #endif - Unsafe.As(ref Unsafe.Add(ref b, 16)) = 0; - Unsafe.As(ref Unsafe.Add(ref b, 20)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 16)) = 0; + Unsafe.As(ref Unsafe.Add(ref b, 20)) = 0; return; } @@ -238,7 +238,7 @@ public static unsafe void ClearWithoutReferences(ref byte b, nuint byteLength) if (((nuint)Unsafe.AsPointer(ref b) & 2) != 0) goto IntAligned; } - Unsafe.As(ref Unsafe.AddByteOffset(ref b, i)) = 0; + Unsafe.As(ref Unsafe.AddByteOffset(ref b, i)) = 0; i += 2; } @@ -254,7 +254,7 @@ public static unsafe void ClearWithoutReferences(ref byte b, nuint byteLength) if ((((nuint)Unsafe.AsPointer(ref b) - 1) & 4) == 0) { - Unsafe.As(ref Unsafe.AddByteOffset(ref b, i)) = 0; + Unsafe.As(ref Unsafe.AddByteOffset(ref b, i)) = 0; i += 4; } @@ -286,10 +286,10 @@ public static unsafe void ClearWithoutReferences(ref byte b, nuint byteLength) Unsafe.As(ref Unsafe.AddByteOffset(ref b, i)) = 0; Unsafe.As(ref Unsafe.AddByteOffset(ref b, i + 8)) = 0; #else - Unsafe.As(ref Unsafe.AddByteOffset(ref b, i)) = 0; - Unsafe.As(ref Unsafe.AddByteOffset(ref b, i + 4)) = 0; - Unsafe.As(ref Unsafe.AddByteOffset(ref b, i + 8)) = 0; - Unsafe.As(ref Unsafe.AddByteOffset(ref b, i + 12)) = 0; + Unsafe.As(ref Unsafe.AddByteOffset(ref b, i)) = 0; + Unsafe.As(ref Unsafe.AddByteOffset(ref b, i + 4)) = 0; + Unsafe.As(ref Unsafe.AddByteOffset(ref b, i + 8)) = 0; + Unsafe.As(ref Unsafe.AddByteOffset(ref b, i + 12)) = 0; #endif i = counter; @@ -304,24 +304,24 @@ public static unsafe void ClearWithoutReferences(ref byte b, nuint byteLength) #if TARGET_64BIT Unsafe.As(ref Unsafe.AddByteOffset(ref b, i)) = 0; #else - Unsafe.As(ref Unsafe.AddByteOffset(ref b, i)) = 0; - Unsafe.As(ref Unsafe.AddByteOffset(ref b, i + 4)) = 0; + Unsafe.As(ref Unsafe.AddByteOffset(ref b, i)) = 0; + Unsafe.As(ref Unsafe.AddByteOffset(ref b, i + 4)) = 0; #endif i += 8; } if ((byteLength & 4) != 0) { - Unsafe.As(ref Unsafe.AddByteOffset(ref b, i)) = 0; + Unsafe.As(ref Unsafe.AddByteOffset(ref b, i)) = 0; i += 4; } if ((byteLength & 2) != 0) { - Unsafe.As(ref Unsafe.AddByteOffset(ref b, i)) = 0; + Unsafe.As(ref Unsafe.AddByteOffset(ref b, i)) = 0; i += 2; } if ((byteLength & 1) != 0) { - Unsafe.AddByteOffset(ref b, i) = 0; + Unsafe.AddByteOffset(ref b, i) = 0; // We're not using i after this, so not needed // i += 1; } diff --git a/src/libraries/System.Private.CoreLib/src/System/StackOverflowException.cs b/src/libraries/System.Private.CoreLib/src/System/StackOverflowException.cs index 3c75a77aa4ed09..e1daed4e8ed512 100644 --- a/src/libraries/System.Private.CoreLib/src/System/StackOverflowException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/StackOverflowException.cs @@ -10,12 +10,13 @@ ** =============================================================================*/ +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class StackOverflowException : SystemException { public StackOverflowException() diff --git a/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs b/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs index b3758d335c9006..66b9432dfe24fd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.Comparison.cs @@ -215,7 +215,7 @@ public static int Compare(string? strA, string? strB, bool ignoreCase) // for meaning of different comparisonType. public static int Compare(string? strA, string? strB, StringComparison comparisonType) { - if (object.ReferenceEquals(strA, strB)) + if (ReferenceEquals(strA, strB)) { CheckStringComparison(comparisonType); return 0; @@ -371,7 +371,7 @@ public static int Compare(string? strA, int indexA, string? strB, int indexB, in if (strA == null || strB == null) { - if (object.ReferenceEquals(strA, strB)) + if (ReferenceEquals(strA, strB)) { // They're both null return 0; @@ -394,7 +394,7 @@ public static int Compare(string? strA, int indexA, string? strB, int indexB, in throw new ArgumentOutOfRangeException(paramName, SR.ArgumentOutOfRange_IndexMustBeLessOrEqual); } - if (length == 0 || (object.ReferenceEquals(strA, strB) && indexA == indexB)) + if (length == 0 || (ReferenceEquals(strA, strB) && indexA == indexB)) { return 0; } @@ -425,7 +425,7 @@ public static int Compare(string? strA, int indexA, string? strB, int indexB, in // public static int CompareOrdinal(string? strA, string? strB) { - if (object.ReferenceEquals(strA, strB)) + if (ReferenceEquals(strA, strB)) { return 0; } @@ -460,7 +460,7 @@ public static int CompareOrdinal(string? strA, int indexA, string? strB, int ind { if (strA == null || strB == null) { - if (object.ReferenceEquals(strA, strB)) + if (ReferenceEquals(strA, strB)) { // They're both null return 0; @@ -489,7 +489,7 @@ public static int CompareOrdinal(string? strA, int indexA, string? strB, int ind throw new ArgumentOutOfRangeException(paramName, SR.ArgumentOutOfRange_IndexMustBeLessOrEqual); } - if (length == 0 || (object.ReferenceEquals(strA, strB) && indexA == indexB)) + if (length == 0 || (ReferenceEquals(strA, strB) && indexA == indexB)) { return 0; } @@ -520,7 +520,7 @@ public int CompareTo(object? value) // public int CompareTo(string? strB) { - return string.Compare(this, strB, StringComparison.CurrentCulture); + return Compare(this, strB, StringComparison.CurrentCulture); } // Determines whether a specified string is a suffix of the current instance. @@ -610,7 +610,7 @@ public bool EndsWith(char value) // Determines whether two strings match. public override bool Equals([NotNullWhen(true)] object? obj) { - if (object.ReferenceEquals(this, obj)) + if (ReferenceEquals(this, obj)) return true; if (!(obj is string str)) @@ -626,7 +626,7 @@ public override bool Equals([NotNullWhen(true)] object? obj) [Intrinsic] // Unrolled and vectorized for half-constant input public bool Equals([NotNullWhen(true)] string? value) { - if (object.ReferenceEquals(this, value)) + if (ReferenceEquals(this, value)) return true; // NOTE: No need to worry about casting to object here. @@ -645,7 +645,7 @@ public bool Equals([NotNullWhen(true)] string? value) [Intrinsic] // Unrolled and vectorized for half-constant input (Ordinal) public bool Equals([NotNullWhen(true)] string? value, StringComparison comparisonType) { - if (object.ReferenceEquals(this, value)) + if (ReferenceEquals(this, value)) { CheckStringComparison(comparisonType); return true; @@ -687,7 +687,7 @@ public bool Equals([NotNullWhen(true)] string? value, StringComparison compariso [Intrinsic] // Unrolled and vectorized for half-constant input public static bool Equals(string? a, string? b) { - if (object.ReferenceEquals(a, b)) + if (ReferenceEquals(a, b)) { return true; } @@ -703,7 +703,7 @@ public static bool Equals(string? a, string? b) [Intrinsic] // Unrolled and vectorized for half-constant input (Ordinal) public static bool Equals(string? a, string? b, StringComparison comparisonType) { - if (object.ReferenceEquals(a, b)) + if (ReferenceEquals(a, b)) { CheckStringComparison(comparisonType); return true; @@ -741,9 +741,9 @@ public static bool Equals(string? a, string? b, StringComparison comparisonType) } } - public static bool operator ==(string? a, string? b) => string.Equals(a, b); + public static bool operator ==(string? a, string? b) => Equals(a, b); - public static bool operator !=(string? a, string? b) => !string.Equals(a, b); + public static bool operator !=(string? a, string? b) => !Equals(a, b); // Gets a hash code for this string. If strings A and B are such that A.Equals(B), then // they will return the same hash code. @@ -904,7 +904,7 @@ static int GetNonRandomizedHashCodeOrdinalIgnoreCaseSlow(string str) Span scratch = (uint)length < 64 ? stackalloc char[64] : (borrowedArr = ArrayPool.Shared.Rent(length + 1)); - int charsWritten = System.Globalization.Ordinal.ToUpperOrdinal(str, scratch); + int charsWritten = Ordinal.ToUpperOrdinal(str, scratch); Debug.Assert(charsWritten == length); scratch[length] = '\0'; 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 df5a986db396ab..39d0baf753f962 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.Manipulation.cs @@ -66,8 +66,8 @@ public static string Concat(params object?[] args) if (args.Length <= 1) { return args.Length == 0 ? - string.Empty : - args[0]?.ToString() ?? string.Empty; + Empty : + args[0]?.ToString() ?? Empty; } // We need to get an intermediary string array @@ -87,7 +87,7 @@ public static string Concat(params object?[] args) { object? value = args[i]; - string toString = value?.ToString() ?? string.Empty; // We need to handle both the cases when value or value.ToString() is null + string toString = value?.ToString() ?? Empty; // We need to handle both the cases when value or value.ToString() is null strings[i] = toString; totalLength += toString.Length; @@ -101,7 +101,7 @@ public static string Concat(params object?[] args) // If all of the ToStrings are null/empty, just return string.Empty if (totalLength == 0) { - return string.Empty; + return Empty; } string result = FastAllocateString(totalLength); @@ -131,13 +131,13 @@ public static string Concat(IEnumerable values) using (IEnumerator en = values.GetEnumerator()) { if (!en.MoveNext()) - return string.Empty; + return Empty; string? firstValue = en.Current; if (!en.MoveNext()) { - return firstValue ?? string.Empty; + return firstValue ?? Empty; } var result = new ValueStringBuilder(stackalloc char[StackallocCharBufferSizeLimit]); @@ -160,7 +160,7 @@ public static string Concat(string? str0, string? str1) { if (IsNullOrEmpty(str1)) { - return string.Empty; + return Empty; } return str1; } @@ -359,8 +359,8 @@ public static string Concat(params string?[] values) if (values.Length <= 1) { return values.Length == 0 ? - string.Empty : - values[0] ?? string.Empty; + Empty : + values[0] ?? Empty; } // It's possible that the input values array could be changed concurrently on another @@ -389,7 +389,7 @@ public static string Concat(params string?[] values) int totalLength = (int)totalLengthLong; if (totalLength == 0) { - return string.Empty; + return Empty; } // Allocate a new string and copy each input string into it @@ -398,7 +398,7 @@ public static string Concat(params string?[] values) for (int i = 0; i < values.Length; i++) { string? value = values[i]; - if (!string.IsNullOrEmpty(value)) + if (!IsNullOrEmpty(value)) { int valueLen = value.Length; if (valueLen > totalLength - copiedLength) @@ -1361,7 +1361,7 @@ private string ReplaceHelper(int oldValueLength, string newValue, ReadOnlySpan /// This method searches for all newline sequences within the string and canonicalizes them to the /// newline sequence provided by . If - /// is , all newline sequences within the string will be removed. + /// is , all newline sequences within the string will be removed. /// /// It is not recommended that protocol parsers utilize this API. Protocol specifications often /// mandate specific newline sequences. For example, HTTP/1.1 (RFC 8615) mandates that the request @@ -1604,12 +1604,12 @@ private string[] SplitInternal(ReadOnlySpan separators, int count, StringS public string[] Split(string? separator, StringSplitOptions options = StringSplitOptions.None) { - return SplitInternal(separator ?? string.Empty, null, int.MaxValue, options); + return SplitInternal(separator ?? Empty, null, int.MaxValue, options); } public string[] Split(string? separator, int count, StringSplitOptions options = StringSplitOptions.None) { - return SplitInternal(separator ?? string.Empty, null, count, options); + return SplitInternal(separator ?? Empty, null, count, options); } public string[] Split(string[]? separator, StringSplitOptions options) @@ -1753,7 +1753,7 @@ private string[] SplitWithoutPostProcessing(ReadOnlySpan sepList, ReadOnlyS { // We had a separator character at the end of a string. Rather than just allowing // a null character, we'll replace the last element in the array with an empty string. - splitStrings[arrIndex] = string.Empty; + splitStrings[arrIndex] = Empty; } return splitStrings; @@ -2301,7 +2301,7 @@ private string CreateTrimmedString(int start, int end) int len = end - start + 1; return len == Length ? this : - len == 0 ? string.Empty : + len == 0 ? Empty : InternalSubString(start, len); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/String.cs b/src/libraries/System.Private.CoreLib/src/System/String.cs index 672bdf72b73382..f3429dd18aa0d6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/String.cs +++ b/src/libraries/System.Private.CoreLib/src/System/String.cs @@ -23,7 +23,7 @@ namespace System [Serializable] [NonVersionable] // This only applies to field layout - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed partial class String : IComparable, IEnumerable, @@ -409,7 +409,7 @@ public unsafe void CopyTo(int sourceIndex, char[] destination, int destinationIn /// Copies the contents of this string into the destination span. /// The span into which to copy this string's contents. - /// The destination span is shorter than the source string. + /// The destination span is shorter than the source string. [MethodImpl(MethodImplOptions.AggressiveInlining)] public void CopyTo(Span destination) { @@ -498,7 +498,7 @@ public static bool IsNullOrWhiteSpace([NotNullWhen(false)] string? value) /// /// Returns a reference to the first element of the String. If the string is null, an access will throw a NullReferenceException. /// - [System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)] + [EditorBrowsable(EditorBrowsableState.Never)] [NonVersionable] public ref readonly char GetPinnableReference() => ref _firstChar; diff --git a/src/libraries/System.Private.CoreLib/src/System/StringComparer.cs b/src/libraries/System.Private.CoreLib/src/System/StringComparer.cs index 8edcece63e8c01..78ebf6c9c3c5d7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/StringComparer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/StringComparer.cs @@ -5,12 +5,13 @@ using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Globalization; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public abstract class StringComparer : IComparer, IEqualityComparer, IComparer, IEqualityComparer { public static StringComparer InvariantCulture => CultureAwareComparer.InvariantCaseSensitiveInstance; @@ -208,7 +209,7 @@ public int GetHashCode(object obj) } [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class CultureAwareComparer : StringComparer, ISerializable { internal static readonly CultureAwareComparer InvariantCaseSensitiveInstance = new CultureAwareComparer(CompareInfo.Invariant, CompareOptions.None); @@ -247,7 +248,7 @@ private CultureAwareComparer(SerializationInfo info, StreamingContext context) public override int Compare(string? x, string? y) { - if (object.ReferenceEquals(x, y)) return 0; + if (ReferenceEquals(x, y)) return 0; if (x == null) return -1; if (y == null) return 1; return _compareInfo.Compare(x, y, _options); @@ -255,7 +256,7 @@ public override int Compare(string? x, string? y) public override bool Equals(string? x, string? y) { - if (object.ReferenceEquals(x, y)) return true; + if (ReferenceEquals(x, y)) return true; if (x == null || y == null) return false; return _compareInfo.Compare(x, y, _options) == 0; } @@ -297,7 +298,7 @@ private protected override bool IsWellKnownCultureAwareComparerCore([NotNullWhen } [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class OrdinalComparer : StringComparer { private readonly bool _ignoreCase; // Do not rename (binary serialization) @@ -318,7 +319,7 @@ public override int Compare(string? x, string? y) if (_ignoreCase) { - return System.Globalization.Ordinal.CompareStringIgnoreCase(ref x.GetRawStringData(), x.Length, ref y.GetRawStringData(), y.Length); + return Globalization.Ordinal.CompareStringIgnoreCase(ref x.GetRawStringData(), x.Length, ref y.GetRawStringData(), y.Length); } return string.CompareOrdinal(x, y); @@ -337,7 +338,7 @@ public override bool Equals(string? x, string? y) { return false; } - return System.Globalization.Ordinal.EqualsIgnoreCase(ref x.GetRawStringData(), ref y.GetRawStringData(), x.Length); + return Globalization.Ordinal.EqualsIgnoreCase(ref x.GetRawStringData(), ref y.GetRawStringData(), x.Length); } return x.Equals(y); } @@ -435,7 +436,7 @@ public override int Compare(string? x, string? y) return 1; } - return System.Globalization.Ordinal.CompareStringIgnoreCase(ref x.GetRawStringData(), x.Length, ref y.GetRawStringData(), y.Length); + return Globalization.Ordinal.CompareStringIgnoreCase(ref x.GetRawStringData(), x.Length, ref y.GetRawStringData(), y.Length); } public override bool Equals(string? x, string? y) @@ -455,7 +456,7 @@ public override bool Equals(string? x, string? y) return false; } - return System.Globalization.Ordinal.EqualsIgnoreCase(ref x.GetRawStringData(), ref y.GetRawStringData(), x.Length); + return Globalization.Ordinal.EqualsIgnoreCase(ref x.GetRawStringData(), ref y.GetRawStringData(), x.Length); } public override int GetHashCode(string obj) diff --git a/src/libraries/System.Private.CoreLib/src/System/SystemException.cs b/src/libraries/System.Private.CoreLib/src/System/SystemException.cs index bc27ed3f05d541..fca0b0e6a459c6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/SystemException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/SystemException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class SystemException : Exception { public SystemException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/ASCIIEncoding.cs b/src/libraries/System.Private.CoreLib/src/System/Text/ASCIIEncoding.cs index 4d02033b642bfb..99fec9d87362e6 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/ASCIIEncoding.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/ASCIIEncoding.cs @@ -48,7 +48,7 @@ public override object Clone() // The initialization code will not be run until a static member of the class is referenced internal static readonly ASCIIEncodingSealed s_default = new ASCIIEncodingSealed(); - public ASCIIEncoding() : base(Encoding.CodePageASCII) + public ASCIIEncoding() : base(CodePageASCII) { } diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.CaseConversion.cs b/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.CaseConversion.cs index a9cdc30f570e06..3db74d75044f4e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.CaseConversion.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/Ascii.CaseConversion.cs @@ -339,7 +339,7 @@ private static unsafe nuint ChangeCase(TFrom* pSrc, TTo* pD if (conversionIsWidthPreserving) { - Unsafe.WriteUnaligned(&pDest[i], nextBlockAsUInt64); + Unsafe.WriteUnaligned(&pDest[i], nextBlockAsUInt64); } else { @@ -354,7 +354,7 @@ private static unsafe nuint ChangeCase(TFrom* pSrc, TTo* pD { Vector128 blockAsVectorOfUInt16 = blockAsVectorOfUInt64.AsUInt16(); Vector128 narrowedBlock = Vector128.Narrow(blockAsVectorOfUInt16, blockAsVectorOfUInt16).AsUInt32(); - Unsafe.WriteUnaligned(&pDest[i], narrowedBlock.ToScalar()); + Unsafe.WriteUnaligned(&pDest[i], narrowedBlock.ToScalar()); } } @@ -398,7 +398,7 @@ private static unsafe nuint ChangeCase(TFrom* pSrc, TTo* pD if (conversionIsWidthPreserving) { - Unsafe.WriteUnaligned(&pDest[i], nextBlockAsUInt32); + Unsafe.WriteUnaligned(&pDest[i], nextBlockAsUInt32); } else { @@ -408,13 +408,13 @@ private static unsafe nuint ChangeCase(TFrom* pSrc, TTo* pD if (conversionIsWidening) { Vector128 widenedBlock = Vector128.WidenLower(blockAsVectorOfUInt32.AsByte()).AsUInt64(); - Unsafe.WriteUnaligned(&pDest[i], widenedBlock.ToScalar()); + Unsafe.WriteUnaligned(&pDest[i], widenedBlock.ToScalar()); } else { Vector128 blockAsVectorOfUInt16 = blockAsVectorOfUInt32.AsUInt16(); Vector128 narrowedBlock = Vector128.Narrow(blockAsVectorOfUInt16, blockAsVectorOfUInt16).AsUInt16(); - Unsafe.WriteUnaligned(&pDest[i], narrowedBlock.ToScalar()); + Unsafe.WriteUnaligned(&pDest[i], narrowedBlock.ToScalar()); } } 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 cbec6d4acdb3f2..8696fca8123f11 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 @@ -1100,7 +1100,7 @@ private static void NarrowFourUtf16CharsToAsciiAndWriteToBuffer(ref byte outputB Vector128 vecWide = Sse2.X64.ConvertScalarToVector128UInt64(value).AsInt16(); Vector128 vecNarrow = Sse2.PackUnsignedSaturate(vecWide, vecWide).AsUInt32(); - Unsafe.WriteUnaligned(ref outputBuffer, Sse2.ConvertToUInt32(vecNarrow)); + Unsafe.WriteUnaligned(ref outputBuffer, Sse2.ConvertToUInt32(vecNarrow)); } else if (AdvSimd.IsSupported) { @@ -1109,7 +1109,7 @@ private static void NarrowFourUtf16CharsToAsciiAndWriteToBuffer(ref byte outputB Vector128 vecWide = Vector128.CreateScalarUnsafe(value).AsInt16(); Vector64 lower = AdvSimd.ExtractNarrowingSaturateUnsignedLower(vecWide); - Unsafe.WriteUnaligned(ref outputBuffer, lower.AsUInt32().ToScalar()); + Unsafe.WriteUnaligned(ref outputBuffer, lower.AsUInt32().ToScalar()); } else @@ -1245,7 +1245,7 @@ internal static unsafe nuint NarrowUtf16ToAscii(char* pUtf16Buffer, byte* pAscii // TODO: Is the below logic also valid for big-endian platforms? Vector asciiVector = Vector.Narrow(utf16VectorHigh, utf16VectorLow); - Unsafe.WriteUnaligned>(pAsciiBuffer + currentOffset, asciiVector); + Unsafe.WriteUnaligned(pAsciiBuffer + currentOffset, asciiVector); currentOffset += SizeOfVector; } while (currentOffset <= finalOffsetWhereCanLoop); @@ -1727,8 +1727,8 @@ internal static unsafe nuint WidenAsciiToUtf16(byte* pAsciiBuffer, char* pUtf16B Vector.Widen(Vector.AsVectorByte(asciiVector), out Vector utf16LowVector, out Vector utf16HighVector); // TODO: Is the below logic also valid for big-endian platforms? - Unsafe.WriteUnaligned>(pUtf16Buffer + currentOffset, utf16LowVector); - Unsafe.WriteUnaligned>(pUtf16Buffer + currentOffset + Vector.Count, utf16HighVector); + Unsafe.WriteUnaligned(pUtf16Buffer + currentOffset, utf16LowVector); + Unsafe.WriteUnaligned(pUtf16Buffer + currentOffset + Vector.Count, utf16HighVector); currentOffset += SizeOfVector; } while (currentOffset <= finalOffsetWhereCanLoop); @@ -1846,13 +1846,13 @@ internal static void WidenFourAsciiBytesToUtf16AndWriteToBuffer(ref char outputB { Vector128 vecNarrow = AdvSimd.DuplicateToVector128(value).AsByte(); Vector128 vecWide = AdvSimd.Arm64.ZipLow(vecNarrow, Vector128.Zero).AsUInt64(); - Unsafe.WriteUnaligned(ref Unsafe.As(ref outputBuffer), vecWide.ToScalar()); + Unsafe.WriteUnaligned(ref Unsafe.As(ref outputBuffer), vecWide.ToScalar()); } else if (Vector128.IsHardwareAccelerated) { Vector128 vecNarrow = Vector128.CreateScalar(value).AsByte(); Vector128 vecWide = Vector128.WidenLower(vecNarrow).AsUInt64(); - Unsafe.WriteUnaligned(ref Unsafe.As(ref outputBuffer), vecWide.ToScalar()); + Unsafe.WriteUnaligned(ref Unsafe.As(ref outputBuffer), vecWide.ToScalar()); } else { diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/DecoderExceptionFallback.cs b/src/libraries/System.Private.CoreLib/src/System/Text/DecoderExceptionFallback.cs index 06470463438371..d0b036834f0438 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/DecoderExceptionFallback.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/DecoderExceptionFallback.cs @@ -3,6 +3,7 @@ using System.Diagnostics.CodeAnalysis; using System.Globalization; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Text @@ -69,7 +70,7 @@ private static void Throw(byte[] bytesUnknown, int index) // Exception for decoding unknown byte sequences. [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class DecoderFallbackException : ArgumentException { private readonly byte[]? _bytesUnknown; diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/EncoderExceptionFallback.cs b/src/libraries/System.Private.CoreLib/src/System/Text/EncoderExceptionFallback.cs index a2295863caa006..fa249cd2d29d23 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/EncoderExceptionFallback.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/EncoderExceptionFallback.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Text @@ -68,7 +69,7 @@ public override bool Fallback(char charUnknownHigh, char charUnknownLow, int ind } [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class EncoderFallbackException : ArgumentException { private readonly char _charUnknown; diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/Encoding.Internal.cs b/src/libraries/System.Private.CoreLib/src/System/Text/Encoding.Internal.cs index 5ccf6b9039b8e0..48ed1db1ca69be 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/Encoding.Internal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/Encoding.Internal.cs @@ -573,7 +573,7 @@ private unsafe int GetBytesWithFallback(char* pOriginalChars, int originalCharCo } /// - /// Transcodes chars to bytes, using or if needed. + /// Transcodes chars to bytes, using or if needed. /// /// /// The total number of bytes written to (based on ). @@ -1174,7 +1174,7 @@ private protected unsafe int GetCharsWithFallback(byte* pOriginalBytes, int orig } /// - /// Transcodes bytes to chars, using or if needed. + /// Transcodes bytes to chars, using or if needed. /// /// /// The total number of chars written to (based on ). diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/Latin1Encoding.cs b/src/libraries/System.Private.CoreLib/src/System/Text/Latin1Encoding.cs index 7dd5ee233bcd9c..1dd51c10522069 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/Latin1Encoding.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/Latin1Encoding.cs @@ -19,7 +19,7 @@ internal partial class Latin1Encoding : Encoding internal static readonly Latin1EncodingSealed s_default = new Latin1EncodingSealed(); // We only use the best-fit table, of which ASCII is a superset for us. - public Latin1Encoding() : base(Encoding.ISO_8859_1) + public Latin1Encoding() : base(ISO_8859_1) { } diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/Latin1Utility.Helpers.cs b/src/libraries/System.Private.CoreLib/src/System/Text/Latin1Utility.Helpers.cs index c9ba5c25f7419c..53aeff7566499d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/Latin1Utility.Helpers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/Latin1Utility.Helpers.cs @@ -57,7 +57,7 @@ private static void NarrowFourUtf16CharsToLatin1AndWriteToBuffer(ref byte output Vector128 vecWide = Sse2.X64.ConvertScalarToVector128UInt64(value).AsInt16(); Vector128 vecNarrow = Sse2.PackUnsignedSaturate(vecWide, vecWide).AsUInt32(); - Unsafe.WriteUnaligned(ref outputBuffer, Sse2.ConvertToUInt32(vecNarrow)); + Unsafe.WriteUnaligned(ref outputBuffer, Sse2.ConvertToUInt32(vecNarrow)); } else { diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/Latin1Utility.cs b/src/libraries/System.Private.CoreLib/src/System/Text/Latin1Utility.cs index 92f4c259c9f976..e8cd792243e314 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/Latin1Utility.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/Latin1Utility.cs @@ -620,7 +620,7 @@ public static unsafe nuint NarrowUtf16ToLatin1(char* pUtf16Buffer, byte* pLatin1 // TODO: Is the below logic also valid for big-endian platforms? Vector latin1Vector = Vector.Narrow(utf16VectorHigh, utf16VectorLow); - Unsafe.WriteUnaligned>(pLatin1Buffer + currentOffset, latin1Vector); + Unsafe.WriteUnaligned(pLatin1Buffer + currentOffset, latin1Vector); currentOffset += SizeOfVector; } while (currentOffset <= finalOffsetWhereCanLoop); @@ -1088,8 +1088,8 @@ private static unsafe void WidenLatin1ToUtf16_Fallback(byte* pLatin1Buffer, char Vector.Widen(Vector.AsVectorByte(latin1Vector), out Vector utf16LowVector, out Vector utf16HighVector); // TODO: Is the below logic also valid for big-endian platforms? - Unsafe.WriteUnaligned>(pUtf16Buffer + currentOffset, utf16LowVector); - Unsafe.WriteUnaligned>(pUtf16Buffer + currentOffset + Vector.Count, utf16HighVector); + Unsafe.WriteUnaligned(pUtf16Buffer + currentOffset, utf16LowVector); + Unsafe.WriteUnaligned(pUtf16Buffer + currentOffset + Vector.Count, utf16HighVector); currentOffset += SizeOfVector; } while (currentOffset <= finalOffsetWhereCanIterate); 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 395e5094e6d5cd..6be755d5958261 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/StringBuilder.cs @@ -20,7 +20,7 @@ namespace System.Text // object unless specified otherwise. This class may be used in conjunction with the String // class to carry out modifications upon strings. [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed partial class StringBuilder : ISerializable { // A StringBuilder is internally represented as a linked list of blocks each of which holds @@ -232,7 +232,7 @@ void ISerializable.GetObjectData(SerializationInfo info, StreamingContext contex info.AddValue(ThreadIDField, 0); } - [System.Diagnostics.Conditional("DEBUG")] + [Conditional("DEBUG")] private void AssertInvariants() { Debug.Assert(m_ChunkOffset + m_ChunkChars.Length >= m_ChunkOffset, "The length of the string is greater than int.MaxValue."); @@ -534,7 +534,7 @@ public struct ChunkEnumerator /// /// Implement IEnumerable.GetEnumerator() to return 'this' as the IEnumerator /// - [ComponentModel.EditorBrowsable(ComponentModel.EditorBrowsableState.Never)] // Only here to make foreach work + [EditorBrowsable(EditorBrowsableState.Never)] // Only here to make foreach work public ChunkEnumerator GetEnumerator() { return this; } /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/UTF7Encoding.cs b/src/libraries/System.Private.CoreLib/src/System/Text/UTF7Encoding.cs index b618734d401e6a..ede61e51d6d7ad 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/UTF7Encoding.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/UTF7Encoding.cs @@ -394,14 +394,14 @@ internal sealed override unsafe int GetBytes( Debug.Assert(charCount >= 0, "[UTF7Encoding.GetBytes]charCount >=0"); // Get encoder info - UTF7Encoding.Encoder? encoder = (UTF7Encoding.Encoder?)baseEncoder; + Encoder? encoder = (Encoder?)baseEncoder; // Default bits & count int bits = 0; int bitCount = -1; // prepare our helpers - Encoding.EncodingByteBuffer buffer = new Encoding.EncodingByteBuffer( + EncodingByteBuffer buffer = new EncodingByteBuffer( this, encoder, bytes, byteCount, chars, charCount); if (encoder is not null) @@ -543,10 +543,10 @@ internal sealed override unsafe int GetChars( Debug.Assert(charCount >= 0, "[UTF7Encoding.GetChars]charCount >=0"); // Might use a decoder - UTF7Encoding.Decoder? decoder = (UTF7Encoding.Decoder?)baseDecoder; + Decoder? decoder = (Decoder?)baseDecoder; // Get our output buffer info. - Encoding.EncodingCharBuffer buffer = new Encoding.EncodingCharBuffer( + EncodingCharBuffer buffer = new EncodingCharBuffer( this, decoder, chars, charCount, bytes, byteCount); // Get decoder info @@ -702,14 +702,14 @@ internal sealed override unsafe int GetChars( return buffer.Count; } - public override System.Text.Decoder GetDecoder() + public override Text.Decoder GetDecoder() { - return new UTF7Encoding.Decoder(this); + return new Decoder(this); } - public override System.Text.Encoder GetEncoder() + public override Text.Encoder GetEncoder() { - return new UTF7Encoding.Encoder(this); + return new Encoder(this); } public override int GetMaxByteCount(int charCount) diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.Helpers.cs b/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.Helpers.cs index 12921c260eec94..b615ee5edd0ad1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.Helpers.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.Helpers.cs @@ -733,8 +733,8 @@ private static void WriteTwoUtf16CharsAsTwoUtf8ThreeByteSequences(ref byte outpu uint tempA = ((value << 2) & 0x3F00u) | ((value & 0x3Fu) << 16); // = [ 00000000 00xxxxxx 00yyyyyy 00000000 ] uint tempB = ((value >> 4) & 0x0F00_0000u) | ((value >> 12) & 0x0Fu); // = [ 0000ZZZZ 00000000 00000000 0000zzzz ] - Unsafe.WriteUnaligned(ref outputBuffer, tempA + tempB + 0xE080_80E0u); // = [ 1110ZZZZ 10xxxxxx 10yyyyyy 1110zzzz ] - Unsafe.WriteUnaligned(ref Unsafe.Add(ref outputBuffer, 4), (ushort)(((value >> 22) & 0x3Fu) + ((value >> 8) & 0x3F00u) + 0x8080u)); // = [ 10XXXXXX 10YYYYYY ] + Unsafe.WriteUnaligned(ref outputBuffer, tempA + tempB + 0xE080_80E0u); // = [ 1110ZZZZ 10xxxxxx 10yyyyyy 1110zzzz ] + Unsafe.WriteUnaligned(ref Unsafe.Add(ref outputBuffer, 4), (ushort)(((value >> 22) & 0x3Fu) + ((value >> 8) & 0x3F00u) + 0x8080u)); // = [ 10XXXXXX 10YYYYYY ] } else { @@ -767,7 +767,7 @@ private static void WriteFirstUtf16CharAsUtf8ThreeByteSequence(ref byte outputBu uint tempA = (value << 2) & 0x3F00u; // [ 00yyyyyy 00000000 ] uint tempB = ((uint)(ushort)value >> 12); // [ 00000000 0000zzzz ] - Unsafe.WriteUnaligned(ref outputBuffer, (ushort)(tempA + tempB + 0x80E0u)); // [ 10yyyyyy 1110zzzz ] + Unsafe.WriteUnaligned(ref outputBuffer, (ushort)(tempA + tempB + 0x80E0u)); // [ 10yyyyyy 1110zzzz ] Unsafe.Add(ref outputBuffer, 2) = (byte)((value & 0x3Fu) | ~0x7Fu); // [ 10xxxxxx ] } else diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.Transcoding.cs b/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.Transcoding.cs index 76c4bed4d9a769..1a58b8b928b695 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.Transcoding.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/Unicode/Utf8Utility.Transcoding.cs @@ -284,7 +284,7 @@ public static OperationStatus TranscodeToUtf16(byte* pInputBuffer, int inputLeng goto ProcessRemainingBytesSlow; // running out of output buffer } - Unsafe.WriteUnaligned(pOutputBuffer, ExtractTwoCharsPackedFromTwoAdjacentTwoByteSequences(thisDWord)); + Unsafe.WriteUnaligned(pOutputBuffer, ExtractTwoCharsPackedFromTwoAdjacentTwoByteSequences(thisDWord)); pInputBuffer += 4; pOutputBuffer += 2; @@ -624,7 +624,7 @@ public static OperationStatus TranscodeToUtf16(byte* pInputBuffer, int inputLeng goto OutputBufferTooSmall; } - Unsafe.WriteUnaligned(pOutputBuffer, ExtractCharsFromFourByteSequence(thisDWord)); + Unsafe.WriteUnaligned(pOutputBuffer, ExtractCharsFromFourByteSequence(thisDWord)); pInputBuffer += 4; pOutputBuffer += 2; @@ -926,7 +926,7 @@ public static OperationStatus TranscodeToUtf8(char* pInputBuffer, int inputLengt // (Same logic works regardless of endianness.) uint valueToWrite = thisDWord | (thisDWord >> 8); - Unsafe.WriteUnaligned(pOutputBuffer, (ushort)valueToWrite); + Unsafe.WriteUnaligned(pOutputBuffer, (ushort)valueToWrite); pInputBuffer += 2; pOutputBuffer += 2; @@ -1002,7 +1002,7 @@ public static OperationStatus TranscodeToUtf8(char* pInputBuffer, int inputLengt } else { - Unsafe.WriteUnaligned(pOutputBuffer, Sse2.ConvertToUInt32(Sse2.PackUnsignedSaturate(utf16Data, utf16Data).AsUInt32())); + Unsafe.WriteUnaligned(pOutputBuffer, Sse2.ConvertToUInt32(Sse2.PackUnsignedSaturate(utf16Data, utf16Data).AsUInt32())); } pInputBuffer += 4; @@ -1040,7 +1040,7 @@ public static OperationStatus TranscodeToUtf8(char* pInputBuffer, int inputLengt } else { - Unsafe.WriteUnaligned(pOutputBuffer, Sse2.ConvertToUInt32(Sse2.PackUnsignedSaturate(utf16Data, utf16Data).AsUInt32())); + Unsafe.WriteUnaligned(pOutputBuffer, Sse2.ConvertToUInt32(Sse2.PackUnsignedSaturate(utf16Data, utf16Data).AsUInt32())); } pInputBuffer += 4; pOutputBuffer += 4; @@ -1056,7 +1056,7 @@ public static OperationStatus TranscodeToUtf8(char* pInputBuffer, int inputLengt if (Utf16Utility.AllCharsInUInt32AreAscii(thisDWord)) { // [ 00000000 0bbbbbbb | 00000000 0aaaaaaa ] -> [ 00000000 0bbbbbbb | 0bbbbbbb 0aaaaaaa ] - Unsafe.WriteUnaligned(pOutputBuffer, (ushort)(thisDWord | (thisDWord >> 8))); + Unsafe.WriteUnaligned(pOutputBuffer, (ushort)(thisDWord | (thisDWord >> 8))); pInputBuffer += 2; pOutputBuffer += 2; outputBytesRemaining -= 2; @@ -1083,8 +1083,8 @@ public static OperationStatus TranscodeToUtf8(char* pInputBuffer, int inputLengt // [ 00000000 0bbbbbbb | 00000000 0aaaaaaa ] -> [ 00000000 0bbbbbbb | 0bbbbbbb 0aaaaaaa ] // (Same logic works regardless of endianness.) - Unsafe.WriteUnaligned(pOutputBuffer, (ushort)(thisDWord | (thisDWord >> 8))); - Unsafe.WriteUnaligned(pOutputBuffer + 2, (ushort)(secondDWord | (secondDWord >> 8))); + Unsafe.WriteUnaligned(pOutputBuffer, (ushort)(thisDWord | (thisDWord >> 8))); + Unsafe.WriteUnaligned(pOutputBuffer + 2, (ushort)(secondDWord | (secondDWord >> 8))); pInputBuffer += 4; pOutputBuffer += 4; @@ -1104,7 +1104,7 @@ public static OperationStatus TranscodeToUtf8(char* pInputBuffer, int inputLengt { // [ 00000000 0bbbbbbb | 00000000 0aaaaaaa ] -> [ 00000000 0bbbbbbb | 0bbbbbbb 0aaaaaaa ] // (Same logic works regardless of endianness.) - Unsafe.WriteUnaligned(pOutputBuffer, (ushort)(thisDWord | (thisDWord >> 8))); + Unsafe.WriteUnaligned(pOutputBuffer, (ushort)(thisDWord | (thisDWord >> 8))); pInputBuffer += 2; pOutputBuffer += 2; outputBytesRemaining -= 2; @@ -1172,7 +1172,7 @@ public static OperationStatus TranscodeToUtf8(char* pInputBuffer, int inputLengt goto ProcessOneCharFromCurrentDWordAndFinish; // running out of output buffer } - Unsafe.WriteUnaligned(pOutputBuffer, ExtractTwoUtf8TwoByteSequencesFromTwoPackedUtf16Chars(thisDWord)); + Unsafe.WriteUnaligned(pOutputBuffer, ExtractTwoUtf8TwoByteSequencesFromTwoPackedUtf16Chars(thisDWord)); pInputBuffer += 2; pOutputBuffer += 4; @@ -1206,7 +1206,7 @@ public static OperationStatus TranscodeToUtf8(char* pInputBuffer, int inputLengt goto OutputBufferTooSmall; } - Unsafe.WriteUnaligned(pOutputBuffer, (ushort)ExtractUtf8TwoByteSequenceFromFirstUtf16Char(thisDWord)); + Unsafe.WriteUnaligned(pOutputBuffer, (ushort)ExtractUtf8TwoByteSequenceFromFirstUtf16Char(thisDWord)); // The buffer contains a 2-byte sequence followed by 2 bytes that aren't a 2-byte sequence. // Unlikely that a 3-byte sequence would follow a 2-byte sequence, so perhaps remaining @@ -1378,7 +1378,7 @@ public static OperationStatus TranscodeToUtf8(char* pInputBuffer, int inputLengt goto OutputBufferTooSmall; } - Unsafe.WriteUnaligned(pOutputBuffer, ExtractFourUtf8BytesFromSurrogatePair(thisDWord)); + Unsafe.WriteUnaligned(pOutputBuffer, ExtractFourUtf8BytesFromSurrogatePair(thisDWord)); pInputBuffer += 2; pOutputBuffer += 4; diff --git a/src/libraries/System.Private.CoreLib/src/System/Text/UnicodeEncoding.cs b/src/libraries/System.Private.CoreLib/src/System/Text/UnicodeEncoding.cs index e6aaa42e93d5bc..9cf17f76706d79 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Text/UnicodeEncoding.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Text/UnicodeEncoding.cs @@ -734,7 +734,7 @@ internal sealed override unsafe int GetBytes( // else all < 0x8000 so we can use them // We can use these 4 chars. - Unsafe.WriteUnaligned(longBytes, *longChars); + Unsafe.WriteUnaligned(longBytes, *longChars); longChars++; longBytes++; } @@ -978,7 +978,7 @@ internal sealed override unsafe int GetCharCount(byte* bytes, int count, Decoder Debug.Assert(bytes is not null, "[UnicodeEncoding.GetCharCount]bytes!=null"); Debug.Assert(count >= 0, "[UnicodeEncoding.GetCharCount]count >=0"); - UnicodeEncoding.Decoder? decoder = (UnicodeEncoding.Decoder?)baseDecoder; + Decoder? decoder = (Decoder?)baseDecoder; byte* byteEnd = bytes + count; byte* byteStart = bytes; @@ -1303,7 +1303,7 @@ internal sealed override unsafe int GetChars( Debug.Assert(charCount >= 0, "[UnicodeEncoding.GetChars]charCount >=0"); Debug.Assert(bytes is not null, "[UnicodeEncoding.GetChars]bytes!=null"); - UnicodeEncoding.Decoder? decoder = (UnicodeEncoding.Decoder?)baseDecoder; + Decoder? decoder = (Decoder?)baseDecoder; // Need last vars int lastByte = -1; @@ -1398,7 +1398,7 @@ internal sealed override unsafe int GetChars( // else all < 0x8000 so we can use them // We can use these 4 chars. - Unsafe.WriteUnaligned(longChars, *longBytes); + Unsafe.WriteUnaligned(longChars, *longBytes); longBytes++; longChars++; } @@ -1719,14 +1719,14 @@ internal sealed override unsafe int GetChars( return (int)(chars - charStart); } - public override System.Text.Encoder GetEncoder() + public override Encoder GetEncoder() { return new EncoderNLS(this); } - public override System.Text.Decoder GetDecoder() + public override Text.Decoder GetDecoder() { - return new UnicodeEncoding.Decoder(this); + return new Decoder(this); } public override byte[] GetPreamble() @@ -1812,7 +1812,7 @@ public override int GetHashCode() (byteOrderMark ? 4 : 0) + (bigEndian ? 8 : 0); } - private sealed class Decoder : System.Text.DecoderNLS + private sealed class Decoder : DecoderNLS { internal int lastByte = -1; internal char lastChar; diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/AbandonedMutexException.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/AbandonedMutexException.cs index de8353322f442b..f7cfe86f3b6463 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/AbandonedMutexException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/AbandonedMutexException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Threading { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class AbandonedMutexException : SystemException { private int _mutexIndex = -1; diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationToken.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationToken.cs index a07909669de5e0..07106341f868bc 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationToken.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationToken.cs @@ -14,9 +14,9 @@ namespace System.Threading /// A may be created directly in an unchangeable canceled or non-canceled state /// using the CancellationToken's constructors. However, to have a CancellationToken that can change /// from a non-canceled to a canceled state, - /// CancellationTokenSource must be used. + /// CancellationTokenSource must be used. /// CancellationTokenSource exposes the associated CancellationToken that may be canceled by the source through its - /// Token property. + /// Token property. /// /// /// Once canceled, a token may not transition to a non-canceled state, and a token whose @@ -51,7 +51,7 @@ namespace System.Threading /// /// This property indicates whether cancellation has been requested for this token, /// either through the token initially being constructed in a canceled state, or through - /// calling Cancel + /// calling Cancel /// on the token's associated . /// /// @@ -75,15 +75,15 @@ namespace System.Threading public bool CanBeCanceled => _source != null; /// - /// Gets a that is signaled when the token is canceled. + /// Gets a that is signaled when the token is canceled. /// - /// Accessing this property causes a WaitHandle + /// Accessing this property causes a WaitHandle /// to be instantiated. It is preferable to only use this property when necessary, and to then /// dispose the associated instance at the earliest opportunity (disposing /// the source will dispose of this allocated handle). The handle should not be closed or disposed directly. /// - /// The associated CancellationTokenSource has been disposed. + /// The associated CancellationTokenSource has been disposed. public WaitHandle WaitHandle => (_source ?? CancellationTokenSource.s_neverCanceledSource).WaitHandle; // public CancellationToken() @@ -96,7 +96,7 @@ namespace System.Threading internal CancellationToken(CancellationTokenSource? source) => _source = source; /// - /// Initializes the CancellationToken. + /// Initializes the CancellationToken. /// /// /// The canceled state for the token. @@ -113,7 +113,7 @@ public CancellationToken(bool canceled) : this(canceled ? CancellationTokenSourc } /// - /// Registers a delegate that will be called when this CancellationToken is canceled. + /// Registers a delegate that will be called when this CancellationToken is canceled. /// /// /// @@ -122,19 +122,19 @@ public CancellationToken(bool canceled) : this(canceled ? CancellationTokenSourc /// propagated out of this method call. /// /// - /// The current ExecutionContext, if one exists, will be captured + /// The current ExecutionContext, if one exists, will be captured /// along with the delegate and will be used when executing it. /// /// - /// The delegate to be executed when the CancellationToken is canceled. - /// The instance that can + /// The delegate to be executed when the CancellationToken is canceled. + /// The instance that can /// be used to unregister the callback. - /// is null. + /// is null. public CancellationTokenRegistration Register(Action callback) => Register(callback, useSynchronizationContext: false); /// /// Registers a delegate that will be called when this - /// CancellationToken is canceled. + /// CancellationToken is canceled. /// /// /// @@ -143,17 +143,17 @@ public CancellationToken(bool canceled) : this(canceled ? CancellationTokenSourc /// propagated out of this method call. /// /// - /// The current ExecutionContext, if one exists, will be captured + /// The current ExecutionContext, if one exists, will be captured /// along with the delegate and will be used when executing it. /// /// - /// The delegate to be executed when the CancellationToken is canceled. + /// The delegate to be executed when the CancellationToken is canceled. /// A Boolean value that indicates whether to capture - /// the current SynchronizationContext and use it + /// the current SynchronizationContext and use it /// when invoking the . - /// The instance that can + /// The instance that can /// be used to unregister the callback. - /// is null. + /// is null. public CancellationTokenRegistration Register(Action callback, bool useSynchronizationContext) { ArgumentNullException.ThrowIfNull(callback); @@ -166,7 +166,7 @@ public CancellationTokenRegistration Register(Action callback, bool useSynchroni /// /// Registers a delegate that will be called when this - /// CancellationToken is canceled. + /// CancellationToken is canceled. /// /// /// @@ -175,15 +175,15 @@ public CancellationTokenRegistration Register(Action callback, bool useSynchroni /// propagated out of this method call. /// /// - /// The current ExecutionContext, if one exists, will be captured + /// The current ExecutionContext, if one exists, will be captured /// along with the delegate and will be used when executing it. /// /// - /// The delegate to be executed when the CancellationToken is canceled. + /// The delegate to be executed when the CancellationToken is canceled. /// The state to pass to the when the delegate is invoked. This may be null. - /// The instance that can + /// The instance that can /// be used to unregister the callback. - /// is null. + /// is null. public CancellationTokenRegistration Register(Action callback, object? state) => Register(callback, state, useSynchronizationContext: false, useExecutionContext: true); @@ -193,7 +193,7 @@ public CancellationTokenRegistration Register(Action callback, object? /// generates will be propagated out of this method call. The current ExecutionContext, if one exists, /// will be captured along with the delegate and will be used when executing it. The current is not captured. /// - /// The delegate to be executed when the CancellationToken is canceled. + /// The delegate to be executed when the CancellationToken is canceled. /// The state to pass to the when the delegate is invoked. This may be null. /// The instance that can be used to unregister the callback. /// is null. @@ -202,7 +202,7 @@ public CancellationTokenRegistration Register(Action /// /// Registers a delegate that will be called when this - /// CancellationToken is canceled. + /// CancellationToken is canceled. /// /// /// @@ -211,26 +211,26 @@ public CancellationTokenRegistration Register(Action /// propagated out of this method call. /// /// - /// The current ExecutionContext, if one exists, + /// The current ExecutionContext, if one exists, /// will be captured along with the delegate and will be used when executing it. /// /// - /// The delegate to be executed when the CancellationToken is canceled. + /// The delegate to be executed when the CancellationToken is canceled. /// The state to pass to the when the delegate is invoked. This may be null. /// A Boolean value that indicates whether to capture - /// the current SynchronizationContext and use it + /// the current SynchronizationContext and use it /// when invoking the . - /// The instance that can + /// The instance that can /// be used to unregister the callback. - /// is null. - /// The associated CancellationTokenSource has been disposed. + /// is null. + /// The associated CancellationTokenSource has been disposed. public CancellationTokenRegistration Register(Action callback, object? state, bool useSynchronizationContext) => Register(callback, state, useSynchronizationContext, useExecutionContext: true); /// /// Registers a delegate that will be called when this - /// CancellationToken is canceled. + /// CancellationToken is canceled. /// /// /// @@ -238,15 +238,15 @@ public CancellationTokenRegistration Register(Action callback, object? /// Any exception the delegate generates will be propagated out of this method call. /// /// - /// ExecutionContext is not captured nor flowed + /// ExecutionContext is not captured nor flowed /// to the callback's invocation. /// /// - /// The delegate to be executed when the CancellationToken is canceled. + /// The delegate to be executed when the CancellationToken is canceled. /// The state to pass to the when the delegate is invoked. This may be null. - /// The instance that can + /// The instance that can /// be used to unregister the callback. - /// is null. + /// is null. public CancellationTokenRegistration UnsafeRegister(Action callback, object? state) => Register(callback, state, useSynchronizationContext: false, useExecutionContext: false); @@ -255,7 +255,7 @@ public CancellationTokenRegistration UnsafeRegister(Action callback, ob /// If this token is already in the canceled state, the delegate will be run immediately and synchronously. Any exception the delegate /// generates will be propagated out of this method call. is not captured nor flowed to the callback's invocation. /// - /// The delegate to be executed when the CancellationToken is canceled. + /// The delegate to be executed when the CancellationToken is canceled. /// The state to pass to the when the delegate is invoked. This may be null. /// The instance that can be used to unregister the callback. /// is null. @@ -264,7 +264,7 @@ public CancellationTokenRegistration UnsafeRegister(Action /// Registers a delegate that will be called when this - /// CancellationToken is canceled. + /// CancellationToken is canceled. /// /// /// @@ -273,17 +273,17 @@ public CancellationTokenRegistration UnsafeRegister(Action /// - /// The delegate to be executed when the CancellationToken is canceled. + /// The delegate to be executed when the CancellationToken is canceled. /// The state to pass to the when the delegate is invoked. This may be null. /// A Boolean value that indicates whether to capture - /// the current SynchronizationContext and use it + /// the current SynchronizationContext and use it /// when invoking the . /// true to capture the current ExecutionContext; otherwise, false. - /// The instance that can + /// The instance that can /// be used to unregister the callback. - /// is null. - /// The associated CancellationTokenSource has been disposed. + /// is null. + /// The associated CancellationTokenSource has been disposed. private CancellationTokenRegistration Register(Delegate callback, object? state, bool useSynchronizationContext, bool useExecutionContext) { ArgumentNullException.ThrowIfNull(callback); @@ -295,57 +295,57 @@ private CancellationTokenRegistration Register(Delegate callback, object? state, } /// - /// Determines whether the current CancellationToken instance is equal to the + /// Determines whether the current CancellationToken instance is equal to the /// specified token. /// - /// The other CancellationToken to which to compare this + /// The other CancellationToken to which to compare this /// instance. /// True if the instances are equal; otherwise, false. Two tokens are equal if they are associated - /// with the same CancellationTokenSource or if they were both constructed + /// with the same CancellationTokenSource or if they were both constructed /// from public CancellationToken constructors and their values are equal. public bool Equals(CancellationToken other) => _source == other._source; /// - /// Determines whether the current CancellationToken instance is equal to the + /// Determines whether the current CancellationToken instance is equal to the /// specified . /// /// The other object to which to compare this instance. - /// True if is a CancellationToken + /// True if is a CancellationToken /// and if the two instances are equal; otherwise, false. Two tokens are equal if they are associated - /// with the same CancellationTokenSource or if they were both constructed + /// with the same CancellationTokenSource or if they were both constructed /// from public CancellationToken constructors and their values are equal. - /// An associated CancellationTokenSource has been disposed. + /// An associated CancellationTokenSource has been disposed. public override bool Equals([NotNullWhen(true)] object? other) => other is CancellationToken && Equals((CancellationToken)other); /// - /// Serves as a hash function for a CancellationToken. + /// Serves as a hash function for a CancellationToken. /// - /// A hash code for the current CancellationToken instance. + /// A hash code for the current CancellationToken instance. public override int GetHashCode() => (_source ?? CancellationTokenSource.s_neverCanceledSource).GetHashCode(); /// - /// Determines whether two CancellationToken instances are equal. + /// Determines whether two CancellationToken instances are equal. /// /// The first instance. /// The second instance. /// True if the instances are equal; otherwise, false. - /// An associated CancellationTokenSource has been disposed. + /// An associated CancellationTokenSource has been disposed. public static bool operator ==(CancellationToken left, CancellationToken right) => left.Equals(right); /// - /// Determines whether two CancellationToken instances are not equal. + /// Determines whether two CancellationToken instances are not equal. /// /// The first instance. /// The second instance. /// True if the instances are not equal; otherwise, false. - /// An associated CancellationTokenSource has been disposed. + /// An associated CancellationTokenSource has been disposed. public static bool operator !=(CancellationToken left, CancellationToken right) => !left.Equals(right); /// - /// Throws a OperationCanceledException if + /// Throws a OperationCanceledException if /// this token has had cancellation requested. /// /// @@ -355,7 +355,7 @@ private CancellationTokenRegistration Register(Delegate callback, object? state, /// throw new OperationCanceledException(token); /// /// - /// The token has had cancellation requested. + /// The token has had cancellation requested. public void ThrowIfCancellationRequested() { if (IsCancellationRequested) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenRegistration.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenRegistration.cs index 9e080d71109b36..345b41a32acff7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenRegistration.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenRegistration.cs @@ -7,7 +7,7 @@ namespace System.Threading { /// - /// Represents a callback delegate that has been registered with a CancellationToken. + /// Represents a callback delegate that has been registered with a CancellationToken. /// /// /// To unregister a callback, dispose the corresponding Registration instance. @@ -25,7 +25,7 @@ internal CancellationTokenRegistration(long id, CancellationTokenSource.Callback /// /// Disposes of the registration and unregisters the target callback from the associated - /// CancellationToken. + /// CancellationToken. /// If the target callback is currently executing, this method will wait until it completes, except /// in the degenerate cases where a callback method unregisters itself. /// @@ -61,7 +61,7 @@ static void WaitForCallbackIfNecessary(long id, CancellationTokenSource.Callback /// /// Disposes of the registration and unregisters the target callback from the associated - /// CancellationToken. + /// CancellationToken. /// The returned will complete once the associated callback /// is unregistered without having executed or once it's finished executing, except /// in the degenerate case where the callback itself is unregistering itself. @@ -104,14 +104,14 @@ _node is CancellationTokenSource.CallbackNode node ? /// /// Disposes of the registration and unregisters the target callback from the associated - /// CancellationToken. + /// CancellationToken. /// public bool Unregister() => _node is CancellationTokenSource.CallbackNode node && node.Registrations.Unregister(_id, node); /// /// Determines whether two CancellationTokenRegistration + /// cref="CancellationTokenRegistration">CancellationTokenRegistration /// instances are equal. /// /// The first instance. @@ -120,7 +120,7 @@ public bool Unregister() => public static bool operator ==(CancellationTokenRegistration left, CancellationTokenRegistration right) => left.Equals(right); /// - /// Determines whether two CancellationTokenRegistration instances are not equal. + /// Determines whether two CancellationTokenRegistration instances are not equal. /// /// The first instance. /// The second instance. @@ -128,33 +128,33 @@ public bool Unregister() => public static bool operator !=(CancellationTokenRegistration left, CancellationTokenRegistration right) => !left.Equals(right); /// - /// Determines whether the current CancellationTokenRegistration instance is equal to the + /// Determines whether the current CancellationTokenRegistration instance is equal to the /// specified . /// /// The other object to which to compare this instance. /// True, if both this and are equal. False, otherwise. - /// Two CancellationTokenRegistration instances are equal if + /// Two CancellationTokenRegistration instances are equal if /// they both refer to the output of a single call to the same Register method of a - /// CancellationToken. + /// CancellationToken. /// public override bool Equals([NotNullWhen(true)] object? obj) => obj is CancellationTokenRegistration other && Equals(other); /// - /// Determines whether the current CancellationToken instance is equal to the + /// Determines whether the current CancellationToken instance is equal to the /// specified . /// - /// The other CancellationTokenRegistration to which to compare this instance. + /// The other CancellationTokenRegistration to which to compare this instance. /// True, if both this and are equal. False, otherwise. - /// Two CancellationTokenRegistration instances are equal if + /// Two CancellationTokenRegistration instances are equal if /// they both refer to the output of a single call to the same Register method of a - /// CancellationToken. + /// CancellationToken. /// public bool Equals(CancellationTokenRegistration other) => _node == other._node && _id == other._id; /// - /// Serves as a hash function for a CancellationTokenRegistration.. + /// Serves as a hash function for a CancellationTokenRegistration.. /// - /// A hash code for the current CancellationTokenRegistration instance. + /// A hash code for the current CancellationTokenRegistration instance. public override int GetHashCode() => _node != null ? _node.GetHashCode() ^ _id.GetHashCode() : _id.GetHashCode(); } } 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 ec6f8e3c200815..fcdbf884734577 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/CancellationTokenSource.cs @@ -40,7 +40,7 @@ private static void TimerCallback(object? state) => // separated out into a name private bool _disposed; /// ITimer used by CancelAfter and Timer-related ctors. Used instead of Timer to avoid extra allocations and because the rooted behavior is desired. private volatile ITimer? _timer; - /// lazily initialized and returned from . + /// lazily initialized and returned from . private volatile ManualResetEvent? _kernelEvent; /// Registration state for the source. /// Lazily-initialized, also serving as the lock to protect its contained state. @@ -860,7 +860,7 @@ public static CancellationTokenSource CreateLinkedTokenSource(CancellationToken /// /// The CancellationToken instances to observe. /// A that is linked to the source tokens. - /// is null. + /// is null. public static CancellationTokenSource CreateLinkedTokenSource(params CancellationToken[] tokens) { ArgumentNullException.ThrowIfNull(tokens); @@ -1134,28 +1134,16 @@ public void WaitForCallbackToComplete(long id) /// It is ok to call this method if the callback has already finished. /// Calling this method before the target callback has been selected for execution would be an error. /// - public ValueTask WaitForCallbackToCompleteAsync(long id) + public async ValueTask WaitForCallbackToCompleteAsync(long id) { - // If the currently executing callback is not the target one, then the target one has already - // completed and we can simply return. This should be the most common case, as the caller - // calls if we're currently canceling but doesn't know what callback is running, if any. - if (Volatile.Read(ref ExecutingCallbackId) != id) + // Employ an async loop that'll poll for the currently executing callback to complete. While such polling isn't + // ideal, we expect this to be a rare case (disposing while the associated callback is running), and brief when + // it happens (so the polling will be minimal), and making this work with a callback mechanism will add additional + // cost to other more common cases. + while (Volatile.Read(ref ExecutingCallbackId) == id) { - return default; + await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); } - - // The specified callback is actually running: queue an async loop that'll poll for the currently executing - // callback to complete. While such polling isn't ideal, we expect this to be a rare case (disposing while - // the associated callback is running), and brief when it happens (so the polling will be minimal), and making - // this work with a callback mechanism will add additional cost to other more common cases. - return new ValueTask(Task.Factory.StartNew(static async s => - { - var state = (TupleSlim)s!; - while (Volatile.Read(ref state.Item1.ExecutingCallbackId) == state.Item2) - { - await Task.Yield(); - } - }, new TupleSlim(this, id), CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default).Unwrap()); } /// Enters the lock for this instance. The current thread must not be holding the lock, but that is not validated. 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 ea47926d3dc4b9..bbc7631a61694d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ExecutionContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ExecutionContext.cs @@ -214,7 +214,7 @@ internal static void RunInternal(ExecutionContext? executionContext, ContextCall /// /// /// To revert to the current execution context; capture it before Restore, and Restore it again. - /// It will not automatically be reverted unlike . + /// It will not automatically be reverted unlike . /// /// The ExecutionContext to set. /// is null. @@ -350,7 +350,7 @@ internal static void ResetThreadPoolThread(Thread currentThread) } } - [System.Diagnostics.Conditional("DEBUG")] + [Conditional("DEBUG")] internal static void CheckThreadPoolAndContextsAreDefault() { Debug.Assert(!Thread.IsThreadStartSupported || Thread.CurrentThread.IsThreadPoolThread); // there are no dedicated threadpool threads on runtimes where we can't start threads 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 751035f548df53..f40564b6746e63 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Interlocked.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Interlocked.cs @@ -69,6 +69,24 @@ public static uint Exchange(ref uint location1, uint value) => public static ulong Exchange(ref ulong location1, ulong value) => (ulong)Exchange(ref Unsafe.As(ref location1), (long)value); + /// Sets a single-precision floating point number to a specified value and returns the original value, as an atomic operation. + /// The variable to set to the specified value. + /// The value to which the parameter is set. + /// The original value of . + /// The address of location1 is a null pointer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float Exchange(ref float location1, float value) + => Unsafe.BitCast(Exchange(ref Unsafe.As(ref location1), Unsafe.BitCast(value))); + + /// Sets a double-precision floating point number to a specified value and returns the original value, as an atomic operation. + /// The variable to set to the specified value. + /// The value to which the parameter is set. + /// The original value of . + /// The address of location1 is a null pointer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double Exchange(ref double location1, double value) + => Unsafe.BitCast(Exchange(ref Unsafe.As(ref location1), Unsafe.BitCast(value))); + /// Sets a platform-specific handle or pointer to a specified value and returns the original value, as an atomic operation. /// The variable to set to the specified value. /// The value to which the parameter is set. @@ -81,7 +99,7 @@ public static IntPtr Exchange(ref IntPtr location1, IntPtr value) #if TARGET_64BIT return (IntPtr)Interlocked.Exchange(ref Unsafe.As(ref location1), (long)value); #else - return (IntPtr)Interlocked.Exchange(ref Unsafe.As(ref location1), (int)value); + return (IntPtr)Exchange(ref Unsafe.As(ref location1), (int)value); #endif #pragma warning restore CA2020 } @@ -98,7 +116,7 @@ public static UIntPtr Exchange(ref UIntPtr location1, UIntPtr value) #if TARGET_64BIT return (UIntPtr)Interlocked.Exchange(ref Unsafe.As(ref location1), (long)value); #else - return (UIntPtr)Interlocked.Exchange(ref Unsafe.As(ref location1), (int)value); + return (UIntPtr)Exchange(ref Unsafe.As(ref location1), (int)value); #endif } #endregion @@ -126,6 +144,26 @@ public static uint CompareExchange(ref uint location1, uint value, uint comparan public static ulong CompareExchange(ref ulong location1, ulong value, ulong comparand) => (ulong)CompareExchange(ref Unsafe.As(ref location1), (long)value, (long)comparand); + /// Compares two single-precision floating point numbers for equality and, if they are equal, replaces the first value. + /// The destination, whose value is compared with and possibly replaced. + /// The value that replaces the destination value if the comparison results in equality. + /// The value that is compared to the value at . + /// The original value in . + /// The address of is a null pointer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float CompareExchange(ref float location1, float value, float comparand) + => Unsafe.BitCast(CompareExchange(ref Unsafe.As(ref location1), Unsafe.BitCast(value), Unsafe.BitCast(comparand))); + + /// Compares two double-precision floating point numbers for equality and, if they are equal, replaces the first value. + /// The destination, whose value is compared with and possibly replaced. + /// The value that replaces the destination value if the comparison results in equality. + /// The value that is compared to the value at . + /// The original value in . + /// The address of is a null pointer. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double CompareExchange(ref double location1, double value, double comparand) + => Unsafe.BitCast(CompareExchange(ref Unsafe.As(ref location1), Unsafe.BitCast(value), Unsafe.BitCast(comparand))); + /// Compares two platform-specific handles or pointers for equality and, if they are equal, replaces the first one. /// The destination , whose value is compared with the value of and possibly replaced by . /// The that replaces the destination value if the comparison results in equality. @@ -139,7 +177,7 @@ public static IntPtr CompareExchange(ref IntPtr location1, IntPtr value, IntPtr #if TARGET_64BIT return (IntPtr)Interlocked.CompareExchange(ref Unsafe.As(ref location1), (long)value, (long)comparand); #else - return (IntPtr)Interlocked.CompareExchange(ref Unsafe.As(ref location1), (int)value, (int)comparand); + return (IntPtr)CompareExchange(ref Unsafe.As(ref location1), (int)value, (int)comparand); #endif #pragma warning restore CA2020 } @@ -157,7 +195,7 @@ public static UIntPtr CompareExchange(ref UIntPtr location1, UIntPtr value, UInt #if TARGET_64BIT return (UIntPtr)Interlocked.CompareExchange(ref Unsafe.As(ref location1), (long)value, (long)comparand); #else - return (UIntPtr)Interlocked.CompareExchange(ref Unsafe.As(ref location1), (int)value, (int)comparand); + return (UIntPtr)CompareExchange(ref Unsafe.As(ref location1), (int)value, (int)comparand); #endif } #endregion @@ -325,5 +363,23 @@ public static long Or(ref long location1, long value) public static ulong Or(ref ulong location1, ulong value) => (ulong)Or(ref Unsafe.As(ref location1), (long)value); #endregion + + #region MemoryBarrier + /// + /// Synchronizes memory access as follows: + /// The processor that executes the current thread cannot reorder instructions in such a way that memory accesses before + /// the call to execute after memory accesses that follow the call to . + /// + [Intrinsic] + public static void MemoryBarrier() => MemoryBarrier(); + + /// + /// Synchronizes memory access as follows: + /// The processor that executes the current thread cannot reorder instructions in such a way that memory reads before + /// the call to execute after memory accesses that follow the call to . + /// + [Intrinsic] + internal static void ReadMemoryBarrier() => ReadMemoryBarrier(); + #endregion } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/LazyInitializer.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/LazyInitializer.cs index 824616221a5f7e..55186b542c9583 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/LazyInitializer.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/LazyInitializer.cs @@ -29,9 +29,9 @@ public static class LazyInitializer /// A reference of type to initialize if it has not /// already been initialized. /// The initialized reference of type . - /// Type does not have a default + /// Type does not have a default /// constructor. - /// + /// /// Permissions to access the constructor of type were missing. /// /// @@ -78,12 +78,12 @@ public static class LazyInitializer /// The reference type of the reference to be initialized. /// The reference of type to initialize if it has not /// already been initialized. - /// The invoked to initialize the + /// The invoked to initialize the /// reference. /// The initialized reference of type . - /// Type does not have a + /// Type does not have a /// default constructor. - /// returned + /// returned /// null. /// /// @@ -192,7 +192,7 @@ private static T EnsureInitializedCore([NotNull] ref T? target, Func value /// A reference to an object used as the mutually exclusive lock for initializing /// . If is null, and if the target hasn't already /// been initialized, a new object will be instantiated. - /// The invoked to initialize the + /// The invoked to initialize the /// reference or value. /// The initialized value of type . public static T EnsureInitialized([AllowNull] ref T target, ref bool initialized, [NotNullIfNotNull(nameof(syncLock))] ref object? syncLock, Func valueFactory) @@ -216,7 +216,7 @@ public static T EnsureInitialized([AllowNull] ref T target, ref bool initiali /// A reference to a location containing a mutual exclusive lock. If is null, /// a new object will be instantiated. /// - /// The to invoke in order to produce the lazily-initialized value. + /// The to invoke in order to produce the lazily-initialized value. /// /// The initialized object. private static T EnsureInitializedCore([AllowNull] ref T target, ref bool initialized, [NotNull] ref object? syncLock, Func valueFactory) @@ -242,7 +242,7 @@ private static T EnsureInitializedCore([AllowNull] ref T target, ref bool ini /// A reference to an object used as the mutually exclusive lock for initializing /// . If is null, and if the target hasn't already /// been initialized, a new object will be instantiated. - /// The invoked to initialize the reference. + /// The invoked to initialize the reference. /// The initialized value of type . public static T EnsureInitialized([NotNull] ref T? target, [NotNullIfNotNull(nameof(syncLock))] ref object? syncLock, Func valueFactory) where T : class => Volatile.Read(ref target!) ?? EnsureInitializedCore(ref target, ref syncLock, valueFactory); @@ -256,7 +256,7 @@ public static T EnsureInitialized([NotNull] ref T? target, [NotNullIfNotNull( /// A reference to a location containing a mutual exclusive lock. If is null, /// a new object will be instantiated. /// - /// The to invoke in order to produce the lazily-initialized value. + /// The to invoke in order to produce the lazily-initialized value. /// /// The initialized object. private static T EnsureInitializedCore([NotNull] ref T? target, [NotNull] ref object? syncLock, Func valueFactory) where T : class diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/LazyThreadSafetyMode.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/LazyThreadSafetyMode.cs index f117c579598eee..1474e7e6cab6d7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/LazyThreadSafetyMode.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/LazyThreadSafetyMode.cs @@ -10,33 +10,33 @@ namespace System.Threading { /// - /// Specifies how a instance should synchronize access among multiple threads. + /// Specifies how a instance should synchronize access among multiple threads. /// public enum LazyThreadSafetyMode { /// - /// This mode makes no guarantees around the thread-safety of the instance. If used from multiple threads, the behavior of the is undefined. - /// This mode should be used when a is guaranteed to never be initialized from more than one thread simultaneously and high performance is crucial. - /// If valueFactory throws an exception when the is initialized, the exception will be cached and returned on subsequent accesses to Value. Also, if valueFactory recursively - /// accesses Value on this instance, a will be thrown. + /// This mode makes no guarantees around the thread-safety of the instance. If used from multiple threads, the behavior of the is undefined. + /// This mode should be used when a is guaranteed to never be initialized from more than one thread simultaneously and high performance is crucial. + /// If valueFactory throws an exception when the is initialized, the exception will be cached and returned on subsequent accesses to Value. Also, if valueFactory recursively + /// accesses Value on this instance, a will be thrown. /// None, /// - /// When multiple threads attempt to simultaneously initialize a instance, this mode allows each thread to execute the - /// valueFactory but only the first thread to complete initialization will be allowed to set the final value of the . + /// When multiple threads attempt to simultaneously initialize a instance, this mode allows each thread to execute the + /// valueFactory but only the first thread to complete initialization will be allowed to set the final value of the . /// Once initialized successfully, any future calls to Value will return the cached result. If valueFactory throws an exception on any thread, that exception will be /// propagated out of Value. If any thread executes valueFactory without throwing an exception and, therefore, successfully sets the value, that value will be returned on /// subsequent accesses to Value from any thread. If no thread succeeds in setting the value, IsValueCreated will remain false and subsequent accesses to Value will result in - /// the valueFactory delegate re-executing. Also, if valueFactory recursively accesses Value on this instance, an exception will NOT be thrown. + /// the valueFactory delegate re-executing. Also, if valueFactory recursively accesses Value on this instance, an exception will NOT be thrown. /// PublicationOnly, /// - /// This mode uses locks to ensure that only a single thread can initialize a instance in a thread-safe manner. In general, - /// taken if this mode is used in conjunction with a valueFactory delegate that uses locks internally, a deadlock can occur if not - /// handled carefully. If valueFactory throws an exception when the is initialized, the exception will be cached and returned on - /// subsequent accesses to Value. Also, if valueFactory recursively accesses Value on this instance, a will be thrown. + /// This mode uses locks to ensure that only a single thread can initialize a instance in a thread-safe manner. In general, + /// taken if this mode is used in conjunction with a valueFactory delegate that uses locks internally, a deadlock can occur if not + /// handled carefully. If valueFactory throws an exception when the is initialized, the exception will be cached and returned on + /// subsequent accesses to Value. Also, if valueFactory recursively accesses Value on this instance, a will be thrown. /// ExecutionAndPublication } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/LockRecursionException.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/LockRecursionException.cs index eae6c61949b78a..5d6f9cc94b38a5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/LockRecursionException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/LockRecursionException.cs @@ -2,13 +2,14 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Threading { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] - public class LockRecursionException : System.Exception + [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + public class LockRecursionException : Exception { public LockRecursionException() { 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 c30c6c496d7e29..24e6f9a983c174 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ManualResetEventSlim.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ManualResetEventSlim.cs @@ -20,7 +20,7 @@ namespace System.Threading // eagerly, instead of waiting for finalization. /// - /// Provides a slimmed down version of . + /// Provides a slimmed down version of . /// /// /// All public and protected members of are thread-safe and may be used @@ -63,10 +63,10 @@ public class ManualResetEventSlim : IDisposable // ----------- // /// - /// Gets the underlying object for this object for this . /// - /// The underlying event object fore this The underlying event object fore this . /// /// Accessing this property forces initialization of an underlying event object if one hasn't @@ -169,7 +169,7 @@ public ManualResetEventSlim(bool initialState) /// to nonsignaled. /// The number of spin waits that will occur before falling back to a true /// wait. - /// is less than + /// is less than /// 0 or greater than the maximum allowed value. public ManualResetEventSlim(bool initialState, int spinCount) { @@ -265,7 +265,7 @@ public void Set() /// Private helper to actually perform the Set. /// /// Indicates whether we are calling Set() during cancellation. - /// The object has been canceled. + /// The object has been canceled. private void Set(bool duringCancellation) { // We need to ensure that IsSet=true does not get reordered past the read of m_eventObj @@ -337,7 +337,7 @@ public void Reset() /// /// Blocks the current thread until the current is set. /// - /// + /// /// The maximum number of waiters has been exceeded. /// /// @@ -352,14 +352,14 @@ public void Wait() /// /// Blocks the current thread until the current receives a signal, - /// while observing a . + /// while observing a . /// - /// The to + /// The to /// observe. - /// + /// /// The maximum number of waiters has been exceeded. /// - /// was + /// was /// canceled. /// /// The caller of this method blocks indefinitely until the current instance is set. The caller will @@ -373,17 +373,17 @@ public void Wait(CancellationToken cancellationToken) /// /// Blocks the current thread until the current is set, using a - /// to measure the time interval. + /// to measure the time interval. /// - /// A that represents the number of milliseconds - /// to wait, or a that represents -1 milliseconds to wait indefinitely. + /// A that represents the number of milliseconds + /// to wait, or a that represents -1 milliseconds to wait indefinitely. /// - /// true if the was set; otherwise, + /// true if the was set; otherwise, /// false. - /// is a negative + /// is a negative /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater /// than . - /// + /// /// The maximum number of waiters has been exceeded. /// [UnsupportedOSPlatform("browser")] @@ -399,22 +399,22 @@ public bool Wait(TimeSpan timeout) /// /// Blocks the current thread until the current is set, using a - /// to measure the time interval, while observing a . + /// to measure the time interval, while observing a . /// - /// A that represents the number of milliseconds - /// to wait, or a that represents -1 milliseconds to wait indefinitely. + /// A that represents the number of milliseconds + /// to wait, or a that represents -1 milliseconds to wait indefinitely. /// - /// The to + /// The to /// observe. - /// true if the was set; otherwise, + /// true if the was set; otherwise, /// false. - /// is a negative + /// is a negative /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater /// than . - /// was canceled. - /// + /// /// The maximum number of waiters has been exceeded. /// [UnsupportedOSPlatform("browser")] @@ -434,11 +434,11 @@ public bool Wait(TimeSpan timeout, CancellationToken cancellationToken) /// /// The number of milliseconds to wait, or (-1) to wait indefinitely. - /// true if the was set; otherwise, + /// true if the was set; otherwise, /// false. - /// is a + /// is a /// negative number other than -1, which represents an infinite time-out. - /// + /// /// The maximum number of waiters has been exceeded. /// [UnsupportedOSPlatform("browser")] @@ -450,20 +450,20 @@ public bool Wait(int millisecondsTimeout) /// /// Blocks the current thread until the current is set, using a /// 32-bit signed integer to measure the time interval, while observing a . + /// cref="CancellationToken"/>. /// /// The number of milliseconds to wait, or (-1) to wait indefinitely. - /// The to + /// The to /// observe. - /// true if the was set; otherwise, + /// true if the was set; otherwise, /// false. - /// is a + /// is a /// negative number other than -1, which represents an infinite time-out. - /// + /// /// The maximum number of waiters has been exceeded. /// - /// was canceled. [UnsupportedOSPlatform("browser")] public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/NativeRuntimeEventSource.PortableThreadPool.NativeSinks.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/NativeRuntimeEventSource.PortableThreadPool.NativeSinks.cs index 3e9cb4e3e3d687..28393f05627fef 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/NativeRuntimeEventSource.PortableThreadPool.NativeSinks.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/NativeRuntimeEventSource.PortableThreadPool.NativeSinks.cs @@ -3,6 +3,7 @@ using System.Threading; using System.Runtime.CompilerServices; +using System.Diagnostics.CodeAnalysis; namespace System.Diagnostics.Tracing { @@ -15,7 +16,7 @@ namespace System.Diagnostics.Tracing // FireEtw* methods auto-generated from ClrEtwAll.man. This ensures that corresponding event sinks are being used // for the native platform. // For implementation of these events not supporting native sinks, refer to NativeRuntimeEventSource.PortableThreadPool.cs. - [CodeAnalysis.SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "NativeRuntimeEventSource is a special case where event methods don't use WriteEvent/WriteEventCore but still need to be instance methods.")] + [SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "NativeRuntimeEventSource is a special case where event methods don't use WriteEvent/WriteEventCore but still need to be instance methods.")] internal sealed partial class NativeRuntimeEventSource : EventSource { // This value does not seem to be used, leaving it as zero for now. It may be useful for a scenario that may involve diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/NativeRuntimeEventSource.PortableThreadPool.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/NativeRuntimeEventSource.PortableThreadPool.cs index d1fcaf7adc6f14..3c3fa3fc700c32 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/NativeRuntimeEventSource.PortableThreadPool.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/NativeRuntimeEventSource.PortableThreadPool.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Threading; +using System.Diagnostics.CodeAnalysis; using System.Diagnostics.Tracing; using System.Runtime.CompilerServices; @@ -70,7 +71,7 @@ public enum ThreadAdjustmentReasonMap : uint CooperativeBlocking, } - [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", Justification = EventSourceSuppressMessage)] [NonEvent] private unsafe void WriteThreadEvent(int eventId, uint numExistingThreads) @@ -130,7 +131,7 @@ public void ThreadPoolWorkerThreadWait( } #pragma warning restore IDE0060 - [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", Justification = EventSourceSuppressMessage)] [Event(54, Level = EventLevel.Informational, Message = Messages.WorkerThreadAdjustmentSample, Task = Tasks.ThreadPoolWorkerThreadAdjustment, Opcode = Opcodes.Sample, Version = 0, Keywords = Keywords.ThreadingKeyword)] public unsafe void ThreadPoolWorkerThreadAdjustmentSample( @@ -151,7 +152,7 @@ public unsafe void ThreadPoolWorkerThreadAdjustmentSample( WriteEventCore(54, 2, data); } - [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", Justification = EventSourceSuppressMessage)] [Event(55, Level = EventLevel.Informational, Message = Messages.WorkerThreadAdjustmentAdjustment, Task = Tasks.ThreadPoolWorkerThreadAdjustment, Opcode = Opcodes.Adjustment, Version = 0, Keywords = Keywords.ThreadingKeyword)] public unsafe void ThreadPoolWorkerThreadAdjustmentAdjustment( @@ -180,7 +181,7 @@ public unsafe void ThreadPoolWorkerThreadAdjustmentAdjustment( WriteEventCore(55, 4, data); } - [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", Justification = EventSourceSuppressMessage)] [Event(56, Level = EventLevel.Verbose, Message = Messages.WorkerThreadAdjustmentStats, Task = Tasks.ThreadPoolWorkerThreadAdjustment, Opcode = Opcodes.Stats, Version = 0, Keywords = Keywords.ThreadingKeyword)] public unsafe void ThreadPoolWorkerThreadAdjustmentStats( @@ -237,7 +238,7 @@ public unsafe void ThreadPoolWorkerThreadAdjustmentStats( WriteEventCore(56, 11, data); } - [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", Justification = EventSourceSuppressMessage)] [Event(63, Level = EventLevel.Verbose, Message = Messages.IOEnqueue, Task = Tasks.ThreadPool, Opcode = Opcodes.IOEnqueue, Version = 0, Keywords = Keywords.ThreadingKeyword | Keywords.ThreadTransferKeyword)] private unsafe void ThreadPoolIOEnqueue( @@ -288,7 +289,7 @@ public void ThreadPoolIOEnqueue(RegisteredWaitHandle registeredWaitHandle) } } - [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", Justification = EventSourceSuppressMessage)] [Event(64, Level = EventLevel.Verbose, Message = Messages.IO, Task = Tasks.ThreadPool, Opcode = Opcodes.IODequeue, Version = 0, Keywords = Keywords.ThreadingKeyword | Keywords.ThreadTransferKeyword)] private unsafe void ThreadPoolIODequeue( @@ -333,7 +334,7 @@ public void ThreadPoolIODequeue(RegisteredWaitHandle registeredWaitHandle) } } - [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", Justification = EventSourceSuppressMessage)] [Event(60, Level = EventLevel.Verbose, Message = Messages.WorkingThreadCount, Task = Tasks.ThreadPoolWorkingThreadCount, Opcode = EventOpcode.Start, Version = 0, Keywords = Keywords.ThreadingKeyword)] public unsafe void ThreadPoolWorkingThreadCount(uint Count, ushort ClrInstanceID = DefaultClrInstanceId) @@ -364,7 +365,7 @@ public unsafe void ThreadPoolIOPack(NativeOverlapped* nativeOverlapped) } } - [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", Justification = EventSourceSuppressMessage)] [Event(65, Level = EventLevel.Verbose, Message = Messages.IO, Task = Tasks.ThreadPool, Opcode = Opcodes.IOPack, Version = 0, Keywords = Keywords.ThreadingKeyword)] private unsafe void ThreadPoolIOPack( @@ -386,7 +387,7 @@ private unsafe void ThreadPoolIOPack( } - [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", Justification = EventSourceSuppressMessage)] [Event(59, Level = EventLevel.Informational, Message = Messages.MinMaxThreads, Task = Tasks.ThreadPoolMinMaxThreads, Opcode = EventOpcode.Info, Version = 0, Keywords = Keywords.ThreadingKeyword)] public unsafe void ThreadPoolMinMaxThreads( diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/RegisteredWaitHandle.Portable.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/RegisteredWaitHandle.Portable.cs index e216cbb78d55c2..359a9062d5db8e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/RegisteredWaitHandle.Portable.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/RegisteredWaitHandle.Portable.cs @@ -11,7 +11,7 @@ namespace System.Threading /// An object representing the registration of a via . /// #if !FEATURE_WASM_THREADS - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [UnsupportedOSPlatform("browser")] #endif public sealed partial class RegisteredWaitHandle : MarshalByRefObject { diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/SemaphoreFullException.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/SemaphoreFullException.cs index e57b02d28e3142..339e637580af8e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/SemaphoreFullException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/SemaphoreFullException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Threading { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class SemaphoreFullException : SystemException { public SemaphoreFullException() : base(SR.Threading_SemaphoreFullException) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs index e167ce326e749d..e95d13cf2812f7 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/SemaphoreSlim.cs @@ -82,9 +82,9 @@ internal TaskNode() : base((object?)null, TaskCreationOptions.RunContinuationsAs public int CurrentCount => m_currentCount; /// - /// Returns a that can be used to wait on the semaphore. + /// Returns a that can be used to wait on the semaphore. /// - /// A that can be used to wait on the + /// A that can be used to wait on the /// semaphore. /// /// A successful wait on the does not imply a successful wait on @@ -92,7 +92,7 @@ internal TaskNode() : base((object?)null, TaskCreationOptions.RunContinuationsAs /// count. exists to allow a thread to block waiting on multiple /// semaphores, but such a wait should be followed by a true wait on the target semaphore. /// - /// The The has been disposed. public WaitHandle AvailableWaitHandle { @@ -125,7 +125,7 @@ public WaitHandle AvailableWaitHandle /// /// The initial number of requests for the semaphore that can be granted /// concurrently. - /// + /// /// is less than 0. public SemaphoreSlim(int initialCount) : this(initialCount, NO_MAXIMUM) @@ -140,7 +140,7 @@ public SemaphoreSlim(int initialCount) /// concurrently. /// The maximum number of requests for the semaphore that can be granted /// concurrently. - /// + /// /// is less than 0. -or- /// is greater than . -or- /// is equal to or less than 0. @@ -169,7 +169,7 @@ public SemaphoreSlim(int initialCount, int maxCount) /// /// Blocks the current thread until it can enter the . /// - /// The current instance has already been + /// The current instance has already been /// disposed. [UnsupportedOSPlatform("browser")] public void Wait() @@ -180,13 +180,13 @@ public void Wait() /// /// Blocks the current thread until it can enter the , while observing a - /// . + /// . /// - /// The token to + /// The token to /// observe. - /// was + /// was /// canceled. - /// The current instance has already been + /// The current instance has already been /// disposed. [UnsupportedOSPlatform("browser")] public void Wait(CancellationToken cancellationToken) @@ -197,14 +197,14 @@ public void Wait(CancellationToken cancellationToken) /// /// Blocks the current thread until it can enter the , using a to measure the time interval. + /// cref="TimeSpan"/> to measure the time interval. /// - /// A that represents the number of milliseconds - /// to wait, or a that represents -1 milliseconds to wait indefinitely. + /// A that represents the number of milliseconds + /// to wait, or a that represents -1 milliseconds to wait indefinitely. /// /// true if the current thread successfully entered the ; /// otherwise, false. - /// is a negative + /// is a negative /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater /// than . [UnsupportedOSPlatform("browser")] @@ -214,7 +214,7 @@ public bool Wait(TimeSpan timeout) long totalMilliseconds = (long)timeout.TotalMilliseconds; if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue) { - throw new System.ArgumentOutOfRangeException( + throw new ArgumentOutOfRangeException( nameof(timeout), timeout, SR.SemaphoreSlim_Wait_TimeoutWrong); } @@ -224,20 +224,20 @@ public bool Wait(TimeSpan timeout) /// /// Blocks the current thread until it can enter the , using a to measure the time interval, while observing a . + /// cref="TimeSpan"/> to measure the time interval, while observing a . /// - /// A that represents the number of milliseconds - /// to wait, or a that represents -1 milliseconds to wait indefinitely. + /// A that represents the number of milliseconds + /// to wait, or a that represents -1 milliseconds to wait indefinitely. /// - /// The to + /// The to /// observe. /// true if the current thread successfully entered the ; /// otherwise, false. - /// is a negative + /// is a negative /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater /// than . - /// was canceled. + /// was canceled. [UnsupportedOSPlatform("browser")] public bool Wait(TimeSpan timeout, CancellationToken cancellationToken) { @@ -245,7 +245,7 @@ public bool Wait(TimeSpan timeout, CancellationToken cancellationToken) long totalMilliseconds = (long)timeout.TotalMilliseconds; if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue) { - throw new System.ArgumentOutOfRangeException( + throw new ArgumentOutOfRangeException( nameof(timeout), timeout, SR.SemaphoreSlim_Wait_TimeoutWrong); } @@ -272,15 +272,15 @@ public bool Wait(int millisecondsTimeout) /// /// Blocks the current thread until it can enter the , /// using a 32-bit signed integer to measure the time interval, - /// while observing a . + /// while observing a . /// /// The number of milliseconds to wait, or (-1) to /// wait indefinitely. - /// The to observe. + /// The to observe. /// true if the current thread successfully entered the ; otherwise, false. /// is a negative number other than -1, /// which represents an infinite time-out. - /// was canceled. + /// was canceled. [UnsupportedOSPlatform("browser")] public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken) { @@ -481,13 +481,13 @@ public Task WaitAsync() /// /// Asynchronously waits to enter the , while observing a - /// . + /// . /// /// A task that will complete when the semaphore has been entered. /// - /// The token to observe. + /// The token to observe. /// - /// + /// /// The current instance has already been disposed. /// public Task WaitAsync(CancellationToken cancellationToken) @@ -506,7 +506,7 @@ public Task WaitAsync(CancellationToken cancellationToken) /// A task that will complete with a result of true if the current thread successfully entered /// the , otherwise with a result of false. /// - /// The current instance has already been + /// The current instance has already been /// disposed. /// is a negative number other than -1, /// which represents an infinite time-out. @@ -518,21 +518,21 @@ public Task WaitAsync(int millisecondsTimeout) /// /// Asynchronously waits to enter the , using a to measure the time interval, while observing a - /// . + /// cref="TimeSpan"/> to measure the time interval, while observing a + /// . /// /// - /// A that represents the number of milliseconds - /// to wait, or a that represents -1 milliseconds to wait indefinitely. + /// A that represents the number of milliseconds + /// to wait, or a that represents -1 milliseconds to wait indefinitely. /// /// /// A task that will complete with a result of true if the current thread successfully entered /// the , otherwise with a result of false. /// - /// + /// /// The current instance has already been disposed. /// - /// + /// /// is a negative number other than -1 milliseconds, which represents /// an infinite time-out -or- timeout is greater than . /// @@ -543,20 +543,20 @@ public Task WaitAsync(TimeSpan timeout) /// /// Asynchronously waits to enter the , using a to measure the time interval. + /// cref="TimeSpan"/> to measure the time interval. /// /// - /// A that represents the number of milliseconds - /// to wait, or a that represents -1 milliseconds to wait indefinitely. + /// A that represents the number of milliseconds + /// to wait, or a that represents -1 milliseconds to wait indefinitely. /// /// - /// The token to observe. + /// The token to observe. /// /// /// A task that will complete with a result of true if the current thread successfully entered /// the , otherwise with a result of false. /// - /// + /// /// is a negative number other than -1 milliseconds, which represents /// an infinite time-out -or- timeout is greater than . /// @@ -566,7 +566,7 @@ public Task WaitAsync(TimeSpan timeout, CancellationToken cancellationToke long totalMilliseconds = (long)timeout.TotalMilliseconds; if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue) { - throw new System.ArgumentOutOfRangeException( + throw new ArgumentOutOfRangeException( nameof(timeout), timeout, SR.SemaphoreSlim_Wait_TimeoutWrong); } @@ -577,17 +577,17 @@ public Task WaitAsync(TimeSpan timeout, CancellationToken cancellationToke /// /// Asynchronously waits to enter the , /// using a 32-bit signed integer to measure the time interval, - /// while observing a . + /// while observing a . /// /// /// The number of milliseconds to wait, or (-1) to wait indefinitely. /// - /// The to observe. + /// The to observe. /// /// A task that will complete with a result of true if the current thread successfully entered /// the , otherwise with a result of false. /// - /// The current instance has already been + /// The current instance has already been /// disposed. /// is a negative number other than -1, /// which represents an infinite time-out. @@ -697,14 +697,14 @@ private async Task WaitUntilCountOrTimeoutAsync(TaskNode asyncWaiter, int Debug.Assert(asyncWaiter is not null, "Waiter should have been constructed"); Debug.Assert(Monitor.IsEntered(m_lockObjAndDisposed), "Requires the lock be held"); - await new ConfiguredNoThrowAwaiter(asyncWaiter.WaitAsync(TimeSpan.FromMilliseconds(millisecondsTimeout), cancellationToken)); + await ((Task)asyncWaiter.WaitAsync(TimeSpan.FromMilliseconds(millisecondsTimeout), cancellationToken)).ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing); if (cancellationToken.IsCancellationRequested) { // If we might be running as part of a cancellation callback, force the completion to be asynchronous // so as to maintain semantics similar to when no token is passed (neither Release nor Cancel would invoke // continuations off of this task). - await TaskScheduler.Default; + await Task.CompletedTask.ConfigureAwait(ConfigureAwaitOptions.ForceYielding); } if (asyncWaiter.IsCompleted) @@ -733,25 +733,11 @@ private async Task WaitUntilCountOrTimeoutAsync(TaskNode asyncWaiter, int return await asyncWaiter.ConfigureAwait(false); } - // TODO https://github.com/dotnet/runtime/issues/22144: Replace with official nothrow await solution once available. - /// Awaiter used to await a task.ConfigureAwait(false) but without throwing any exceptions for faulted or canceled tasks. - private readonly struct ConfiguredNoThrowAwaiter : ICriticalNotifyCompletion, IStateMachineBoxAwareAwaiter - { - private readonly Task _task; - public ConfiguredNoThrowAwaiter(Task task) => _task = task; - public ConfiguredNoThrowAwaiter GetAwaiter() => this; - public bool IsCompleted => _task.IsCompleted; - public void GetResult() => _task.MarkExceptionsAsHandled(); - public void OnCompleted(Action continuation) => TaskAwaiter.OnCompletedInternal(_task, continuation, continueOnCapturedContext: false, flowExecutionContext: true); - public void UnsafeOnCompleted(Action continuation) => TaskAwaiter.OnCompletedInternal(_task, continuation, continueOnCapturedContext: false, flowExecutionContext: false); - public void AwaitUnsafeOnCompleted(IAsyncStateMachineBox box) => TaskAwaiter.UnsafeOnCompletedInternal(_task, box, continueOnCapturedContext: false); - } - /// /// Exits the once. /// /// The previous count of the . - /// The current instance has already been + /// The current instance has already been /// disposed. public int Release() { @@ -763,11 +749,11 @@ public int Release() /// /// The number of times to exit the semaphore. /// The previous count of the . - /// is less + /// is less /// than 1. - /// The has + /// The has /// already reached its maximum size. - /// The current instance has already been + /// The current instance has already been /// disposed. public int Release(int releaseCount) { @@ -868,7 +854,7 @@ public void Dispose() /// /// When overridden in a derived class, releases the unmanaged resources used by the - /// , and optionally releases the managed resources. + /// , and optionally releases the managed resources. /// /// true to release both managed and unmanaged resources; /// false to release only unmanaged resources. diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/SpinLock.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/SpinLock.cs index 86b8747be9017e..68b70dc70ff9d0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/SpinLock.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/SpinLock.cs @@ -22,7 +22,7 @@ namespace System.Threading /// /// /// Spin locks can be used for leaf-level locks where the object allocation implied by using a , in size or due to garbage collection pressure, is overly + /// cref="Monitor"/>, in size or due to garbage collection pressure, is overly /// expensive. Avoiding blocking is another reason that a spin lock can be useful, however if you expect /// any significant amount of blocking, you are probably best not using spin locks due to excessive /// spinning. Spinning can be beneficial when locks are fine grained and large in number (for example, a @@ -100,7 +100,7 @@ private static int CompareExchange(ref int location, int value, int comparand, r } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// structure with the option to track thread IDs to improve debugging. /// /// @@ -119,7 +119,7 @@ public SpinLock(bool enableThreadOwnerTracking) } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// structure with the option to track thread IDs to improve debugging. /// /// @@ -139,10 +139,10 @@ public SpinLock(bool enableThreadOwnerTracking) /// /// True if the lock is acquired; otherwise, false. must be initialized to false prior to calling this method. - /// + /// /// Thread ownership tracking is enabled, and the current thread has already acquired this lock. /// - /// + /// /// The argument must be initialized to false prior to calling Enter. /// public void Enter(ref bool lockTaken) @@ -167,10 +167,10 @@ public void Enter(ref bool lockTaken) /// /// True if the lock is acquired; otherwise, false. must be initialized to false prior to calling this method. - /// + /// /// Thread ownership tracking is enabled, and the current thread has already acquired this lock. /// - /// + /// /// The argument must be initialized to false prior to calling TryEnter. /// public void TryEnter(ref bool lockTaken) @@ -204,18 +204,18 @@ public void TryEnter(ref bool lockTaken) /// name="timeout"/> /// has expired. /// - /// A that represents the number of milliseconds - /// to wait, or a that represents -1 milliseconds to wait indefinitely. + /// A that represents the number of milliseconds + /// to wait, or a that represents -1 milliseconds to wait indefinitely. /// /// True if the lock is acquired; otherwise, false. must be initialized to false prior to calling this method. - /// + /// /// Thread ownership tracking is enabled, and the current thread has already acquired this lock. /// - /// + /// /// The argument must be initialized to false prior to calling TryEnter. /// - /// is a negative + /// is a negative /// number other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater /// than milliseconds. /// @@ -225,7 +225,7 @@ public void TryEnter(TimeSpan timeout, ref bool lockTaken) long totalMilliseconds = (long)timeout.TotalMilliseconds; if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue) { - throw new System.ArgumentOutOfRangeException( + throw new ArgumentOutOfRangeException( nameof(timeout), timeout, SR.SpinLock_TryEnter_ArgumentOutOfRange); } @@ -244,16 +244,16 @@ public void TryEnter(TimeSpan timeout, ref bool lockTaken) /// name="millisecondsTimeout"/> has expired. /// /// The number of milliseconds to wait, or (-1) to wait indefinitely. + /// cref="Timeout.Infinite"/> (-1) to wait indefinitely. /// True if the lock is acquired; otherwise, false. must be initialized to false prior to calling this method. - /// + /// /// Thread ownership tracking is enabled, and the current thread has already acquired this lock. /// - /// + /// /// The argument must be initialized to false prior to calling TryEnter. /// - /// is + /// is /// a negative number other than -1, which represents an infinite time-out. public void TryEnter(int millisecondsTimeout, ref bool lockTaken) { @@ -562,7 +562,7 @@ public bool IsHeld /// by the current thread. It is invalid to use this property when the lock was initialized to not /// track thread ownership. /// - /// + /// /// Thread ownership tracking is disabled. /// public bool IsHeldByCurrentThread diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/SpinWait.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/SpinWait.cs index d827208377ab08..540dbf4c98f8b1 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/SpinWait.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/SpinWait.cs @@ -51,9 +51,9 @@ namespace System.Threading /// is a value type, which means that low-level code can utilize SpinWait without /// fear of unnecessary allocation overheads. SpinWait is not generally useful for ordinary applications. /// In most cases, you should use the synchronization classes provided by the .NET Framework, such as - /// . For most purposes where spin waiting is required, however, + /// . For most purposes where spin waiting is required, however, /// the type should be preferred over the method. + /// cref="Thread.SpinWait"/> method. /// /// /// While SpinWait is designed to be used in concurrent applications, it is not designed to be @@ -273,7 +273,7 @@ public static void SpinUntil(Func condition) /// or a TimeSpan that represents -1 milliseconds to wait indefinitely. /// True if the condition is satisfied within the timeout; otherwise, false /// The argument is null. - /// is a negative number + /// is a negative number /// other than -1 milliseconds, which represents an infinite time-out -or- timeout is greater than /// . public static bool SpinUntil(Func condition, TimeSpan timeout) @@ -282,7 +282,7 @@ public static bool SpinUntil(Func condition, TimeSpan timeout) long totalMilliseconds = (long)timeout.TotalMilliseconds; if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue) { - throw new System.ArgumentOutOfRangeException( + throw new ArgumentOutOfRangeException( nameof(timeout), timeout, SR.SpinWait_SpinUntil_TimeoutWrong); } @@ -295,10 +295,10 @@ public static bool SpinUntil(Func condition, TimeSpan timeout) /// /// A delegate to be executed over and over until it returns true. /// The number of milliseconds to wait, or (-1) to wait indefinitely. + /// cref="Timeout.Infinite"/> (-1) to wait indefinitely. /// True if the condition is satisfied within the timeout; otherwise, false /// The argument is null. - /// is a + /// is a /// negative number other than -1, which represents an infinite time-out. public static bool SpinUntil(Func condition, int millisecondsTimeout) { diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/SynchronizationContext.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/SynchronizationContext.cs index 0ec52392c2dde3..9a0f027e9ee3fe 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/SynchronizationContext.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/SynchronizationContext.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.Collections.Generic; + namespace System.Threading { public partial class SynchronizationContext @@ -19,7 +21,8 @@ public SynchronizationContext() public virtual void Send(SendOrPostCallback d, object? state) => d(state); - public virtual void Post(SendOrPostCallback d, object? state) => ThreadPool.QueueUserWorkItem(static s => s.d(s.state), (d, state), preferLocal: false); + public virtual void Post(SendOrPostCallback d, object? state) + => ThreadPool.QueueUserWorkItem(static s => s.Key(s.Value), new KeyValuePair(d, state), preferLocal: false); /// /// Optional override for subclasses, for responding to notification that operation is starting. diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/SynchronizationLockException.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/SynchronizationLockException.cs index d118ddd5c59762..b89d6fbb4b3ad8 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/SynchronizationLockException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/SynchronizationLockException.cs @@ -12,12 +12,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Threading { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class SynchronizationLockException : SystemException { public SynchronizationLockException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs index a8c15f84f19a99..eb52c6b08f3768 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs @@ -24,7 +24,7 @@ namespace System.Threading.Tasks /// tasks while ensuring that concurrent tasks may run concurrently and exclusive tasks never do. /// [DebuggerDisplay("Concurrent={ConcurrentTaskCountForDebugger}, Exclusive={ExclusiveTaskCountForDebugger}, Mode={ModeForDebugger}")] - [DebuggerTypeProxy(typeof(ConcurrentExclusiveSchedulerPair.DebugView))] + [DebuggerTypeProxy(typeof(DebugView))] public class ConcurrentExclusiveSchedulerPair { /// A processing mode to denote what kinds of tasks are currently being processed on this thread. @@ -140,7 +140,7 @@ public void Complete() } } - /// Gets a that will complete when the scheduler has completed processing. + /// Gets a that will complete when the scheduler has completed processing. public Task Completion => EnsureCompletionStateInitialized(); /// Gets the lazily-initialized completion state. @@ -561,7 +561,7 @@ protected internal override void QueueTask(Task task) internal void ExecuteTask(Task task) { Debug.Assert(task != null, "Infrastructure should have provided a non-null task."); - base.TryExecuteTask(task); + TryExecuteTask(task); } /// Tries to execute the task synchronously on this scheduler. @@ -582,7 +582,7 @@ protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQu // We know the implementation of the default scheduler and how it will behave. // As it's the most common underlying scheduler, we optimize for it. - bool isDefaultScheduler = m_pair.m_underlyingTaskScheduler == TaskScheduler.Default; + bool isDefaultScheduler = m_pair.m_underlyingTaskScheduler == Default; // If we're targeting the default scheduler and taskWasPreviouslyQueued is true, // we know that the default scheduler will only allow it to be inlined diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ConfigureAwaitOptions.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ConfigureAwaitOptions.cs new file mode 100644 index 00000000000000..8d3aac1b770923 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ConfigureAwaitOptions.cs @@ -0,0 +1,47 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.Threading.Tasks +{ + /// Options to control behavior when awaiting. + [Flags] + public enum ConfigureAwaitOptions + { + /// No options specified. + /// + /// with a argument behaves + /// identically to using with a argument. + /// + None = 0x0, + + /// + /// Attempt to marshal the continuation back to the original or + /// present on the originating thread at the time of the await. + /// + /// + /// If there is no such context/scheduler, or if this option is not specified, the thread on + /// which the continuation is invoked is unspecified and left up to the determination of the system. + /// with a argument + /// behaves identically to using with a argument. + /// + ContinueOnCapturedContext = 0x1, + + /// + /// Avoids throwing an exception at the completion of awaiting a that ends + /// in the or state. + /// + /// + /// This option is supported only for , + /// not , as for a the + /// operation could end up returning an incorrect and/or invalid result. To use with a , + /// cast to the base type in order to use its . + /// + SuppressThrowing = 0x2, + + /// + /// Forces an await on an already completed to behave as if the + /// wasn't yet completed, such that the current asynchronous method will be forced to yield its execution. + /// + ForceYielding = 0x4, + } +} diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs index 6cce3006175c0c..827d6915dd3252 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Future.cs @@ -25,7 +25,7 @@ namespace System.Threading.Tasks /// /// instances may be created in a variety of ways. The most common approach is by /// using the task's property to retrieve a instance that can be used to create tasks for several + /// cref="TaskFactory{TResult}"/> instance that can be used to create tasks for several /// purposes. For example, to create a that runs a function, the factory's StartNew /// method may be used: /// @@ -45,12 +45,12 @@ namespace System.Threading.Tasks /// schedule it for execution. For performance reasons, the StartNew method should be the /// preferred mechanism for creating and scheduling computational tasks, but for scenarios where creation /// and scheduling must be separated, the constructors may be used, and the task's - /// Start + /// Start /// method may then be used to schedule the task for execution at a later time. /// /// /// All members of , except for - /// Dispose, are thread-safe + /// Dispose, are thread-safe /// and may be used from multiple threads concurrently. /// /// @@ -112,7 +112,7 @@ internal Task(bool canceled, TResult? result, TaskCreationOptions creationOption /// The delegate that represents the code to execute in the task. When the function has completed, /// the task's property will be set to return the result value of the function. /// - /// + /// /// The argument is null. /// public Task(Func function) @@ -130,10 +130,10 @@ public Task(Func function) /// the task's property will be set to return the result value of the function. /// /// The to be assigned to this task. - /// + /// /// The argument is null. /// - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task(Func function, CancellationToken cancellationToken) @@ -150,18 +150,18 @@ public Task(Func function, CancellationToken cancellationToken) /// the task's property will be set to return the result value of the function. /// /// - /// The TaskCreationOptions used to + /// The TaskCreationOptions used to /// customize the task's behavior. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for . + /// cref="TaskCreationOptions"/>. /// public Task(Func function, TaskCreationOptions creationOptions) - : this(function, Task.InternalCurrentIfAttached(creationOptions), default, creationOptions, InternalTaskOptions.None, null) + : this(function, InternalCurrentIfAttached(creationOptions), default, creationOptions, InternalTaskOptions.None, null) { } @@ -174,21 +174,21 @@ public Task(Func function, TaskCreationOptions creationOptions) /// /// The that will be assigned to the new task. /// - /// The TaskCreationOptions used to + /// The TaskCreationOptions used to /// customize the task's behavior. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for . + /// cref="TaskCreationOptions"/>. /// - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task(Func function, CancellationToken cancellationToken, TaskCreationOptions creationOptions) - : this(function, Task.InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null) + : this(function, InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null) { } @@ -200,7 +200,7 @@ public Task(Func function, CancellationToken cancellationToken, TaskCre /// the task's property will be set to return the result value of the function. /// /// An object representing data to be used by the action. - /// + /// /// The argument is null. /// public Task(Func function, object? state) @@ -218,10 +218,10 @@ public Task(Func function, object? state) /// /// An object representing data to be used by the function. /// The to be assigned to the new task. - /// + /// /// The argument is null. /// - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task(Func function, object? state, CancellationToken cancellationToken) @@ -239,18 +239,18 @@ public Task(Func function, object? state, CancellationToken ca /// /// An object representing data to be used by the function. /// - /// The TaskCreationOptions used to + /// The TaskCreationOptions used to /// customize the task's behavior. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for . + /// cref="TaskCreationOptions"/>. /// public Task(Func function, object? state, TaskCreationOptions creationOptions) - : this(function, state, Task.InternalCurrentIfAttached(creationOptions), default, + : this(function, state, InternalCurrentIfAttached(creationOptions), default, creationOptions, InternalTaskOptions.None, null) { } @@ -266,21 +266,21 @@ public Task(Func function, object? state, TaskCreationOptions /// An object representing data to be used by the function. /// The to be assigned to the new task. /// - /// The TaskCreationOptions used to + /// The TaskCreationOptions used to /// customize the task's behavior. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for . + /// cref="TaskCreationOptions"/>. /// - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task(Func function, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions) - : this(function, state, Task.InternalCurrentIfAttached(creationOptions), cancellationToken, + : this(function, state, InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null) { } @@ -481,7 +481,7 @@ internal TResult GetResultCore(bool waitCompletionNotification) /// /// /// The factory returned from is a default instance - /// of , as would result from using + /// of , as would result from using /// the default constructor on the factory type. /// public static new TaskFactory Factory => @@ -512,21 +512,41 @@ internal override void InnerInvoke() #region Await Support - /// Gets an awaiter used to await this . + /// Gets an awaiter used to await this . /// An awaiter instance. public new TaskAwaiter GetAwaiter() { return new TaskAwaiter(this); } - /// Configures an awaiter used to await this . + /// Configures an awaiter used to await this . /// /// true to attempt to marshal the continuation back to the original context captured; otherwise, false. /// /// An object used to await this task. public new ConfiguredTaskAwaitable ConfigureAwait(bool continueOnCapturedContext) { - return new ConfiguredTaskAwaitable(this, continueOnCapturedContext); + return new ConfiguredTaskAwaitable(this, continueOnCapturedContext ? ConfigureAwaitOptions.ContinueOnCapturedContext : ConfigureAwaitOptions.None); + } + + /// Configures an awaiter used to await this . + /// Options used to configure how awaits on this task are performed. + /// An object used to await this task. + /// The argument specifies an invalid value. + public new ConfiguredTaskAwaitable ConfigureAwait(ConfigureAwaitOptions options) + { + if ((options & ~(ConfigureAwaitOptions.ContinueOnCapturedContext | + ConfigureAwaitOptions.ForceYielding)) != 0) + { + ThrowForInvalidOptions(options); + } + + return new ConfiguredTaskAwaitable(this, options); + + static void ThrowForInvalidOptions(ConfigureAwaitOptions options) => + throw ((options & ConfigureAwaitOptions.SuppressThrowing) == 0 ? + new ArgumentOutOfRangeException(nameof(options)) : + new ArgumentOutOfRangeException(nameof(options), SR.TaskT_ConfigureAwait_InvalidOptions)); } #endregion @@ -614,7 +634,7 @@ private Task WaitAsync(uint millisecondsTimeout, TimeProvider timeProvi /// completed, whether it completes due to running to completion successfully, faulting due to an /// unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Action> continuationAction) @@ -637,7 +657,7 @@ public Task ContinueWith(Action> continuationAction) /// completed, whether it completes due to running to completion successfully, faulting due to an /// unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Action> continuationAction, CancellationToken cancellationToken) @@ -662,10 +682,10 @@ public Task ContinueWith(Action> continuationAction, CancellationT /// completed, whether it completes due to running to completion successfully, faulting due to an /// unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Action> continuationAction, TaskScheduler scheduler) @@ -683,9 +703,9 @@ public Task ContinueWith(Action> continuationAction, TaskScheduler /// /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such /// as OnlyOnCanceled, as + /// cref="TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled, as /// well as execution options, such as ExecuteSynchronously. + /// cref="TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously. /// /// A new continuation . /// @@ -694,12 +714,12 @@ public Task ContinueWith(Action> continuationAction, TaskScheduler /// name="continuationOptions"/> parameter are not met, the continuation task will be canceled /// instead of scheduled. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for TaskContinuationOptions. + /// cref="TaskContinuationOptions">TaskContinuationOptions. /// public Task ContinueWith(Action> continuationAction, TaskContinuationOptions continuationOptions) { @@ -717,9 +737,9 @@ public Task ContinueWith(Action> continuationAction, TaskContinuat /// /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such /// as OnlyOnCanceled, as + /// cref="TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled, as /// well as execution options, such as ExecuteSynchronously. + /// cref="TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously. /// /// /// The to associate with the continuation task and to use for its @@ -731,14 +751,14 @@ public Task ContinueWith(Action> continuationAction, TaskContinuat /// completed. If the criteria specified through the parameter /// are not met, the continuation task will be canceled instead of scheduled. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for TaskContinuationOptions. + /// cref="TaskContinuationOptions">TaskContinuationOptions. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Action> continuationAction, CancellationToken cancellationToken, @@ -795,7 +815,7 @@ internal Task ContinueWith(Action> continuationAction, TaskSchedul /// completed, whether it completes due to running to completion successfully, faulting due to an /// unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Action, object?> continuationAction, object? state) @@ -819,7 +839,7 @@ public Task ContinueWith(Action, object?> continuationAction, obje /// completed, whether it completes due to running to completion successfully, faulting due to an /// unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Action, object?> continuationAction, object? state, CancellationToken cancellationToken) @@ -845,10 +865,10 @@ public Task ContinueWith(Action, object?> continuationAction, obje /// completed, whether it completes due to running to completion successfully, faulting due to an /// unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Action, object?> continuationAction, object? state, TaskScheduler scheduler) @@ -867,9 +887,9 @@ public Task ContinueWith(Action, object?> continuationAction, obje /// /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such /// as OnlyOnCanceled, as + /// cref="TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled, as /// well as execution options, such as ExecuteSynchronously. + /// cref="TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously. /// /// A new continuation . /// @@ -878,12 +898,12 @@ public Task ContinueWith(Action, object?> continuationAction, obje /// name="continuationOptions"/> parameter are not met, the continuation task will be canceled /// instead of scheduled. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for TaskContinuationOptions. + /// cref="TaskContinuationOptions">TaskContinuationOptions. /// public Task ContinueWith(Action, object?> continuationAction, object? state, TaskContinuationOptions continuationOptions) { @@ -902,9 +922,9 @@ public Task ContinueWith(Action, object?> continuationAction, obje /// /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such /// as OnlyOnCanceled, as + /// cref="TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled, as /// well as execution options, such as ExecuteSynchronously. + /// cref="TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously. /// /// /// The to associate with the continuation task and to use for its @@ -916,14 +936,14 @@ public Task ContinueWith(Action, object?> continuationAction, obje /// completed. If the criteria specified through the parameter /// are not met, the continuation task will be canceled instead of scheduled. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for TaskContinuationOptions. + /// cref="TaskContinuationOptions">TaskContinuationOptions. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Action, object?> continuationAction, object? state, CancellationToken cancellationToken, @@ -983,12 +1003,12 @@ internal Task ContinueWith(Action, object?> continuationAction, ob /// task has completed, whether it completes due to running to completion successfully, faulting due /// to an unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Func, TNewResult> continuationFunction) { - return ContinueWith(continuationFunction, TaskScheduler.Current, default, TaskContinuationOptions.None); + return ContinueWith(continuationFunction, TaskScheduler.Current, default, TaskContinuationOptions.None); } @@ -1009,15 +1029,15 @@ public Task ContinueWith(Func, TNewResult> /// task has completed, whether it completes due to running to completion successfully, faulting due /// to an unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task ContinueWith(Func, TNewResult> continuationFunction, CancellationToken cancellationToken) { - return ContinueWith(continuationFunction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None); + return ContinueWith(continuationFunction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None); } /// @@ -1039,15 +1059,15 @@ public Task ContinueWith(Func, TNewResult> /// completed, whether it completes due to running to completion successfully, faulting due to an /// unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Func, TNewResult> continuationFunction, TaskScheduler scheduler) { - return ContinueWith(continuationFunction, scheduler, default, TaskContinuationOptions.None); + return ContinueWith(continuationFunction, scheduler, default, TaskContinuationOptions.None); } /// @@ -1063,9 +1083,9 @@ public Task ContinueWith(Func, TNewResult> /// /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such /// as OnlyOnCanceled, as + /// cref="TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled, as /// well as execution options, such as ExecuteSynchronously. + /// cref="TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously. /// /// A new continuation . /// @@ -1080,16 +1100,16 @@ public Task ContinueWith(Func, TNewResult> /// from the ContinueWith call. /// /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for TaskContinuationOptions. + /// cref="TaskContinuationOptions">TaskContinuationOptions. /// public Task ContinueWith(Func, TNewResult> continuationFunction, TaskContinuationOptions continuationOptions) { - return ContinueWith(continuationFunction, TaskScheduler.Current, default, continuationOptions); + return ContinueWith(continuationFunction, TaskScheduler.Current, default, continuationOptions); } /// @@ -1106,9 +1126,9 @@ public Task ContinueWith(Func, TNewResult> /// /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such /// as OnlyOnCanceled, as + /// cref="TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled, as /// well as execution options, such as ExecuteSynchronously. + /// cref="TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously. /// /// /// The to associate with the continuation task and to use for its @@ -1127,23 +1147,23 @@ public Task ContinueWith(Func, TNewResult> /// ContinueWith call. /// /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for TaskContinuationOptions. + /// cref="TaskContinuationOptions">TaskContinuationOptions. /// - /// + /// /// The argument is null. /// - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task ContinueWith(Func, TNewResult> continuationFunction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { - return ContinueWith(continuationFunction, scheduler, cancellationToken, continuationOptions); + return ContinueWith(continuationFunction, scheduler, cancellationToken, continuationOptions); } // Same as the above overload, just with a stack mark. @@ -1197,12 +1217,12 @@ internal Task ContinueWith(Func, TNewResul /// task has completed, whether it completes due to running to completion successfully, faulting due /// to an unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Func, object?, TNewResult> continuationFunction, object? state) { - return ContinueWith(continuationFunction, state, TaskScheduler.Current, default, TaskContinuationOptions.None); + return ContinueWith(continuationFunction, state, TaskScheduler.Current, default, TaskContinuationOptions.None); } @@ -1224,16 +1244,16 @@ public Task ContinueWith(Func, object?, TN /// task has completed, whether it completes due to running to completion successfully, faulting due /// to an unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task ContinueWith(Func, object?, TNewResult> continuationFunction, object? state, CancellationToken cancellationToken) { - return ContinueWith(continuationFunction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None); + return ContinueWith(continuationFunction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None); } /// @@ -1256,16 +1276,16 @@ public Task ContinueWith(Func, object?, TN /// completed, whether it completes due to running to completion successfully, faulting due to an /// unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Func, object?, TNewResult> continuationFunction, object? state, TaskScheduler scheduler) { - return ContinueWith(continuationFunction, state, scheduler, default, TaskContinuationOptions.None); + return ContinueWith(continuationFunction, state, scheduler, default, TaskContinuationOptions.None); } /// @@ -1282,9 +1302,9 @@ public Task ContinueWith(Func, object?, TN /// /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such /// as OnlyOnCanceled, as + /// cref="TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled, as /// well as execution options, such as ExecuteSynchronously. + /// cref="TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously. /// /// A new continuation . /// @@ -1299,17 +1319,17 @@ public Task ContinueWith(Func, object?, TN /// from the ContinueWith call. /// /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for TaskContinuationOptions. + /// cref="TaskContinuationOptions">TaskContinuationOptions. /// public Task ContinueWith(Func, object?, TNewResult> continuationFunction, object? state, TaskContinuationOptions continuationOptions) { - return ContinueWith(continuationFunction, state, TaskScheduler.Current, default, continuationOptions); + return ContinueWith(continuationFunction, state, TaskScheduler.Current, default, continuationOptions); } /// @@ -1327,9 +1347,9 @@ public Task ContinueWith(Func, object?, TN /// /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such /// as OnlyOnCanceled, as + /// cref="TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled, as /// well as execution options, such as ExecuteSynchronously. + /// cref="TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously. /// /// /// The to associate with the continuation task and to use for its @@ -1348,23 +1368,23 @@ public Task ContinueWith(Func, object?, TN /// ContinueWith call. /// /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for TaskContinuationOptions. + /// cref="TaskContinuationOptions">TaskContinuationOptions. /// - /// + /// /// The argument is null. /// - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task ContinueWith(Func, object?, TNewResult> continuationFunction, object? state, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { - return ContinueWith(continuationFunction, state, scheduler, cancellationToken, continuationOptions); + return ContinueWith(continuationFunction, state, scheduler, cancellationToken, continuationOptions); } // Same as the above overload, just with a stack mark. diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/FutureFactory.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/FutureFactory.cs index efeb2dc1204b5a..23cc6fd44ef7b0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/FutureFactory.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/FutureFactory.cs @@ -7,10 +7,10 @@ namespace System.Threading.Tasks { /// /// Provides support for creating and scheduling - /// Task{TResult} objects. + /// Task{TResult} objects. /// /// The type of the results that are available though - /// the Task{TResult} objects that are associated with + /// the Task{TResult} objects that are associated with /// the methods in this class. /// /// @@ -20,7 +20,7 @@ namespace System.Threading.Tasks /// /// /// A default instance of is available through the - /// Task{TResult}.Factory property. + /// Task{TResult}.Factory property. /// /// public class TaskFactory @@ -56,12 +56,12 @@ private TaskScheduler GetDefaultScheduler(Task? currTask) /// /// This constructor creates a instance with a default configuration. The /// property is initialized to - /// TaskCreationOptions.None, the + /// TaskCreationOptions.None, the /// property is initialized to TaskContinuationOptions.None, - /// and the TaskScheduler property is + /// cref="TaskContinuationOptions.None">TaskContinuationOptions.None, + /// and the TaskScheduler property is /// initialized to the current scheduler (see TaskScheduler.Current). + /// cref="TaskScheduler.Current">TaskScheduler.Current). /// public TaskFactory() { @@ -76,12 +76,12 @@ public TaskFactory() /// /// This constructor creates a instance with a default configuration. The /// property is initialized to - /// TaskCreationOptions.None, the + /// TaskCreationOptions.None, the /// property is initialized to TaskContinuationOptions.None, - /// and the TaskScheduler property is + /// cref="TaskContinuationOptions.None">TaskContinuationOptions.None, + /// and the TaskScheduler property is /// initialized to the current scheduler (see TaskScheduler.Current). + /// cref="TaskScheduler.Current">TaskScheduler.Current). /// public TaskFactory(CancellationToken cancellationToken) { @@ -92,20 +92,20 @@ public TaskFactory(CancellationToken cancellationToken) /// Initializes a instance with the specified configuration. /// /// - /// The + /// The /// TaskScheduler to use to schedule any tasks created with this TaskFactory{TResult}. A null value /// indicates that the current TaskScheduler should be used. /// /// /// With this constructor, the /// property is initialized to - /// TaskCreationOptions.None, the + /// TaskCreationOptions.None, the /// property is initialized to TaskContinuationOptions.None, - /// and the TaskScheduler property is + /// cref="TaskContinuationOptions.None">TaskContinuationOptions.None, + /// and the TaskScheduler property is /// initialized to , unless it's null, in which case the property is /// initialized to the current scheduler (see TaskScheduler.Current). + /// cref="TaskScheduler.Current">TaskScheduler.Current). /// public TaskFactory(TaskScheduler? scheduler) // null means to use TaskScheduler.Current { @@ -116,14 +116,14 @@ public TaskFactory(TaskScheduler? scheduler) // null means to use TaskScheduler. /// Initializes a instance with the specified configuration. /// /// - /// The default + /// The default /// TaskCreationOptions to use when creating tasks with this TaskFactory{TResult}. /// /// - /// The default + /// The default /// TaskContinuationOptions to use when creating continuation tasks with this TaskFactory{TResult}. /// - /// + /// /// The exception that is thrown when the /// argument or the /// argument specifies an invalid value. @@ -134,9 +134,9 @@ public TaskFactory(TaskScheduler? scheduler) // null means to use TaskScheduler. /// the /// property is initialized to , and the TaskScheduler property is initialized to the + /// cref="TaskScheduler">TaskScheduler property is initialized to the /// current scheduler (see TaskScheduler.Current). + /// cref="TaskScheduler.Current">TaskScheduler.Current). /// public TaskFactory(TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions) { @@ -154,19 +154,19 @@ public TaskFactory(TaskCreationOptions creationOptions, TaskContinuationOptions /// to tasks created by this unless another CancellationToken is explicitly specified /// while calling the factory methods. /// - /// The default + /// The default /// TaskCreationOptions to use when creating tasks with this TaskFactory{TResult}. /// /// - /// The default + /// The default /// TaskContinuationOptions to use when creating continuation tasks with this TaskFactory{TResult}. /// /// - /// The default + /// The default /// TaskScheduler to use to schedule any Tasks created with this TaskFactory{TResult}. A null value /// indicates that TaskScheduler.Current should be used. /// - /// + /// /// The exception that is thrown when the /// argument or the /// argumentspecifies an invalid value. @@ -177,10 +177,10 @@ public TaskFactory(TaskCreationOptions creationOptions, TaskContinuationOptions /// the /// property is initialized to , and the TaskScheduler property is initialized to + /// cref="TaskScheduler">TaskScheduler property is initialized to /// , unless it's null, in which case the property is initialized to the /// current scheduler (see TaskScheduler.Current). + /// cref="TaskScheduler.Current">TaskScheduler.Current). /// public TaskFactory(CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions, TaskScheduler? scheduler) : this(creationOptions, continuationOptions) @@ -192,7 +192,7 @@ public TaskFactory(CancellationToken cancellationToken, TaskCreationOptions crea /* Properties */ /// - /// Gets the default CancellationToken of this + /// Gets the default CancellationToken of this /// TaskFactory. /// /// @@ -203,19 +203,19 @@ public TaskFactory(CancellationToken cancellationToken, TaskCreationOptions crea public CancellationToken CancellationToken => m_defaultCancellationToken; /// - /// Gets the TaskScheduler of this + /// Gets the TaskScheduler of this /// TaskFactory{TResult}. /// /// /// This property returns the default scheduler for this factory. It will be used to schedule all /// tasks unless another scheduler is explicitly specified during calls to this factory's methods. - /// If null, TaskScheduler.Current + /// If null, TaskScheduler.Current /// will be used. /// public TaskScheduler? Scheduler => m_defaultScheduler; /// - /// Gets the TaskCreationOptions + /// Gets the TaskCreationOptions /// value of this TaskFactory{TResult}. /// /// @@ -225,7 +225,7 @@ public TaskFactory(CancellationToken cancellationToken, TaskCreationOptions crea public TaskCreationOptions CreationOptions => m_defaultCreationOptions; /// - /// Gets the TaskContinuationOptions + /// Gets the TaskContinuationOptions /// value of this TaskFactory{TResult}. /// /// @@ -238,18 +238,18 @@ public TaskFactory(CancellationToken cancellationToken, TaskCreationOptions crea /* StartNew */ /// - /// Creates and starts a . + /// Creates and starts a . /// /// A function delegate that returns the future result to be available through - /// the . - /// The started . - /// The exception that is thrown when the . + /// The started . + /// The exception that is thrown when the /// argument is null. /// /// Calling StartNew is functionally equivalent to creating a using one /// of its constructors and then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -261,22 +261,22 @@ public Task StartNew(Func function) } /// - /// Creates and starts a . + /// Creates and starts a . /// /// A function delegate that returns the future result to be available through - /// the . + /// the . /// The that will be assigned to the new task. - /// The started . - /// The exception that is thrown when the The started . + /// The exception that is thrown when the /// argument is null. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// /// Calling StartNew is functionally equivalent to creating a using one /// of its constructors and then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -288,24 +288,24 @@ public Task StartNew(Func function, CancellationToken cancella } /// - /// Creates and starts a . + /// Creates and starts a . /// /// A function delegate that returns the future result to be available through - /// the . + /// the . /// A TaskCreationOptions value that controls the behavior of the /// created - /// . - /// The started . - /// The exception that is thrown when the . + /// The started . + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. /// /// Calling StartNew is functionally equivalent to creating a using one /// of its constructors and then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -317,35 +317,35 @@ public Task StartNew(Func function, TaskCreationOptions creati } /// - /// Creates and starts a . + /// Creates and starts a . /// /// A function delegate that returns the future result to be available through - /// the . + /// the . /// A TaskCreationOptions value that controls the behavior of the /// created - /// . + /// . /// The that will be assigned to the new task. /// The TaskScheduler - /// that is used to schedule the created + /// cref="TaskScheduler">TaskScheduler + /// that is used to schedule the created /// Task{TResult}. - /// The started . - /// The exception that is thrown when the The started . + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// /// Calling StartNew is functionally equivalent to creating a using one /// of its constructors and then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -357,20 +357,20 @@ public Task StartNew(Func function, CancellationToken cancella } /// - /// Creates and starts a . + /// Creates and starts a . /// /// A function delegate that returns the future result to be available through - /// the . + /// the . /// An object containing data to be used by the /// delegate. - /// The started . - /// The exception that is thrown when the The started . + /// The exception that is thrown when the /// argument is null. /// /// Calling StartNew is functionally equivalent to creating a using one /// of its constructors and then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -382,24 +382,24 @@ public Task StartNew(Func function, object? state) } /// - /// Creates and starts a . + /// Creates and starts a . /// /// A function delegate that returns the future result to be available through - /// the . + /// the . /// An object containing data to be used by the /// delegate. /// The that will be assigned to the new task. - /// The started . - /// The exception that is thrown when the The started . + /// The exception that is thrown when the /// argument is null. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// /// Calling StartNew is functionally equivalent to creating a using one /// of its constructors and then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -411,26 +411,26 @@ public Task StartNew(Func function, object? state, Ca } /// - /// Creates and starts a . + /// Creates and starts a . /// /// A function delegate that returns the future result to be available through - /// the . + /// the . /// An object containing data to be used by the /// delegate. /// A TaskCreationOptions value that controls the behavior of the /// created - /// . - /// The started . - /// The exception that is thrown when the . + /// The started . + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. /// /// Calling StartNew is functionally equivalent to creating a using one /// of its constructors and then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -442,37 +442,37 @@ public Task StartNew(Func function, object? state, Ta } /// - /// Creates and starts a . + /// Creates and starts a . /// /// A function delegate that returns the future result to be available through - /// the . + /// the . /// An object containing data to be used by the /// delegate. /// The that will be assigned to the new task. /// A TaskCreationOptions value that controls the behavior of the /// created - /// . + /// . /// The TaskScheduler - /// that is used to schedule the created + /// cref="TaskScheduler">TaskScheduler + /// that is used to schedule the created /// Task{TResult}. - /// The started . - /// The exception that is thrown when the The started . + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// /// Calling StartNew is functionally equivalent to creating a using one /// of its constructors and then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -544,18 +544,18 @@ private static void FromAsyncCoreLogic( } /// - /// Creates a Task that executes an end - /// method function when a specified IAsyncResult completes. + /// Creates a Task that executes an end + /// method function when a specified IAsyncResult completes. /// /// The IAsyncResult whose completion should trigger the processing of the /// . /// The function delegate that processes the completed . - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// A Task that represents the + /// A Task that represents the /// asynchronous operation. public Task FromAsync(IAsyncResult asyncResult, Func endMethod) { @@ -563,23 +563,23 @@ public Task FromAsync(IAsyncResult asyncResult, Func - /// Creates a Task that executes an end - /// method function when a specified IAsyncResult completes. + /// Creates a Task that executes an end + /// method function when a specified IAsyncResult completes. /// /// The IAsyncResult whose completion should trigger the processing of the /// . /// The function delegate that processes the completed . /// The TaskCreationOptions value that controls the behavior of the - /// created Task. - /// The exception that is thrown when the + /// created Task. + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// A Task that represents the + /// A Task that represents the /// asynchronous operation. public Task FromAsync( IAsyncResult asyncResult, @@ -592,27 +592,27 @@ public Task FromAsync( /// - /// Creates a Task that executes an end - /// method function when a specified IAsyncResult completes. + /// Creates a Task that executes an end + /// method function when a specified IAsyncResult completes. /// /// The IAsyncResult whose completion should trigger the processing of the /// . /// The function delegate that processes the completed . - /// The TaskScheduler + /// The TaskScheduler /// that is used to schedule the task that executes the end method. /// The TaskCreationOptions value that controls the behavior of the - /// created Task. - /// The exception that is thrown when the + /// created Task. + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// A Task that represents the + /// A Task that represents the /// asynchronous operation. public Task FromAsync( IAsyncResult asyncResult, @@ -694,18 +694,18 @@ internal static Task FromAsyncImpl( } /// - /// Creates a Task that represents a pair of + /// Creates a Task that represents a pair of /// begin and end methods that conform to the Asynchronous Programming Model pattern. /// /// The delegate that begins the asynchronous operation. /// The delegate that ends the asynchronous operation. /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The created Task that + /// The created Task that /// represents the asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -718,23 +718,23 @@ public Task FromAsync( } /// - /// Creates a Task that represents a pair of + /// Creates a Task that represents a pair of /// begin and end methods that conform to the Asynchronous Programming Model pattern. /// /// The delegate that begins the asynchronous operation. /// The delegate that ends the asynchronous operation. /// The TaskCreationOptions value that controls the behavior of the - /// created Task. + /// created Task. /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// The created Task that + /// The created Task that /// represents the asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -801,7 +801,7 @@ internal static Task FromAsyncImpl(Func - /// Creates a Task that represents a pair of + /// Creates a Task that represents a pair of /// begin and end methods that conform to the Asynchronous Programming Model pattern. /// /// The type of the first argument passed to the FromAsyncImpl(Func /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The created Task that + /// The created Task that /// represents the asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -830,7 +830,7 @@ public Task FromAsync( } /// - /// Creates a Task that represents a pair of + /// Creates a Task that represents a pair of /// begin and end methods that conform to the Asynchronous Programming Model pattern. /// /// The type of the first argument passed to the FromAsync( /// The first argument passed to the /// delegate. /// The TaskCreationOptions value that controls the behavior of the - /// created Task. + /// created Task. /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// The created Task that + /// The created Task that /// represents the asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -918,7 +918,7 @@ internal static Task FromAsyncImpl(Func - /// Creates a Task that represents a pair of + /// Creates a Task that represents a pair of /// begin and end methods that conform to the Asynchronous Programming Model pattern. /// /// The type of the first argument passed to the FromAsyncImpl(Func /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The created Task that + /// The created Task that /// represents the asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -951,7 +951,7 @@ public Task FromAsync( } /// - /// Creates a Task that represents a pair of + /// Creates a Task that represents a pair of /// begin and end methods that conform to the Asynchronous Programming Model pattern. /// /// The type of the first argument passed to the FromAsync( /// The second argument passed to the /// delegate. /// The TaskCreationOptions value that controls the behavior of the - /// created Task. + /// created Task. /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// The created Task that + /// The created Task that /// represents the asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -1043,7 +1043,7 @@ internal static Task FromAsyncImpl(Func - /// Creates a Task that represents a pair of + /// Creates a Task that represents a pair of /// begin and end methods that conform to the Asynchronous Programming Model pattern. /// /// The type of the first argument passed to the FromAsyncImpl(Func /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The created Task that + /// The created Task that /// represents the asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -1080,7 +1080,7 @@ public Task FromAsync( } /// - /// Creates a Task that represents a pair of + /// Creates a Task that represents a pair of /// begin and end methods that conform to the Asynchronous Programming Model pattern. /// /// The type of the first argument passed to the FromAsync( /// The third argument passed to the /// delegate. /// The TaskCreationOptions value that controls the behavior of the - /// created Task. + /// created Task. /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// The created Task that + /// The created Task that /// represents the asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -1330,20 +1330,20 @@ private static Task CreateCanceledTask(TaskContinuationOptions continua // /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The array of tasks from which to continue. /// The function delegate to execute when all tasks in /// the array have completed. - /// The new continuation Task. - /// The exception that is thrown when the + /// The new continuation Task. + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. public Task ContinueWhenAll(Task[] tasks, Func continuationFunction) { @@ -1353,24 +1353,24 @@ public Task ContinueWhenAll(Task[] tasks, Func continu } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The array of tasks from which to continue. /// The function delegate to execute when all tasks in /// the array have completed. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The new continuation Task. - /// The exception that is thrown when the + /// The new continuation Task. + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task ContinueWhenAll(Task[] tasks, Func continuationFunction, CancellationToken cancellationToken) @@ -1381,30 +1381,30 @@ public Task ContinueWhenAll(Task[] tasks, Func continu } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The array of tasks from which to continue. /// The function delegate to execute when all tasks in the array have completed. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The new continuation Task. - /// The exception that is thrown when the + /// the created continuation Task. + /// The new continuation Task. + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAll. /// public Task ContinueWhenAll(Task[] tasks, Func continuationFunction, TaskContinuationOptions continuationOptions) @@ -1415,40 +1415,40 @@ public Task ContinueWhenAll(Task[] tasks, Func continu } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The array of tasks from which to continue. /// The function delegate to execute when all tasks in the array have completed. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The TaskScheduler + /// the created continuation Task. + /// The TaskScheduler /// that is used to schedule the created continuation Task. - /// The new continuation Task. - /// The exception that is thrown when the + /// cref="Task">Task. + /// The new continuation Task. + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAll. /// public Task ContinueWhenAll(Task[] tasks, Func continuationFunction, @@ -1460,49 +1460,49 @@ public Task ContinueWhenAll(Task[] tasks, Func continu } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The type of the result of the antecedent . /// The array of tasks from which to continue. /// The function delegate to execute when all tasks in the /// array have completed. - /// The new continuation . - /// The exception that is thrown when the + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. public Task ContinueWhenAll(Task[] tasks, Func[], TResult> continuationFunction) { if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction); - return ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler); + return ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler); } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The type of the result of the antecedent . /// The array of tasks from which to continue. /// The function delegate to execute when all tasks in the /// array have completed. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The new continuation . - /// The exception that is thrown when the + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task ContinueWhenAll(Task[] tasks, Func[], TResult> continuationFunction, @@ -1510,35 +1510,35 @@ public Task ContinueWhenAll(Task[ { if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction); - return ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler); + return ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler); } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The type of the result of the antecedent . /// The array of tasks from which to continue. /// The function delegate to execute when all tasks in the /// array have completed. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The new continuation . - /// The exception that is thrown when the + /// the created continuation Task. + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAll. /// public Task ContinueWhenAll(Task[] tasks, Func[], TResult> continuationFunction, @@ -1546,45 +1546,45 @@ public Task ContinueWhenAll(Task[ { if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction); - return ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler); + return ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler); } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The type of the result of the antecedent . /// The array of tasks from which to continue. /// The function delegate to execute when all tasks in the /// array have completed. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The TaskScheduler + /// the created continuation Task. + /// The TaskScheduler /// that is used to schedule the created continuation . - /// The new continuation . - /// The exception that is thrown when the + /// cref="Task{TResult}"/>. + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAll. /// public Task ContinueWhenAll(Task[] tasks, Func[], TResult> continuationFunction, @@ -1592,7 +1592,7 @@ public Task ContinueWhenAll(Task[ { if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction); - return ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler); + return ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler); } @@ -1609,7 +1609,7 @@ internal static Task ContinueWhenAllImpl(Task[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy(tasks); + Task[] tasksCopy = TaskFactory.CheckMultiContinuationTasksAndCopy(tasks); // Bail early if cancellation has been requested. if (cancellationToken.IsCancellationRequested @@ -1625,7 +1625,7 @@ internal static Task ContinueWhenAllImpl(Task( + return starter.ContinueWith( GenericDelegateCache.CWAllFuncDelegate, continuationFunction, scheduler, cancellationToken, continuationOptions); } @@ -1633,7 +1633,7 @@ internal static Task ContinueWhenAllImpl(Task( + return starter.ContinueWith( GenericDelegateCache.CWAllActionDelegate, continuationAction, scheduler, cancellationToken, continuationOptions); } @@ -1696,20 +1696,20 @@ internal static Task ContinueWhenAllImpl(Task[] tasks, // /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The array of tasks from which to continue when one task completes. /// The function delegate to execute when one task in the array completes. - /// The new continuation Task. - /// The exception that is thrown when the + /// The new continuation Task. + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. public Task ContinueWhenAny(Task[] tasks, Func continuationFunction) { @@ -1719,24 +1719,24 @@ public Task ContinueWhenAny(Task[] tasks, Func continuat } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The array of tasks from which to continue when one task completes. /// The function delegate to execute when one task in the array completes. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The new continuation Task. - /// The exception that is thrown when the + /// The new continuation Task. + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task ContinueWhenAny(Task[] tasks, Func continuationFunction, CancellationToken cancellationToken) @@ -1747,30 +1747,30 @@ public Task ContinueWhenAny(Task[] tasks, Func continuat } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The array of tasks from which to continue when one task completes. /// The function delegate to execute when one task in the array completes. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The new continuation Task. - /// The exception that is thrown when the + /// the created continuation Task. + /// The new continuation Task. + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAny. /// public Task ContinueWhenAny(Task[] tasks, Func continuationFunction, TaskContinuationOptions continuationOptions) @@ -1781,40 +1781,40 @@ public Task ContinueWhenAny(Task[] tasks, Func continuat } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The array of tasks from which to continue when one task completes. /// The function delegate to execute when one task in the array completes. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The TaskScheduler + /// the created continuation Task. + /// The TaskScheduler /// that is used to schedule the created continuation Task. - /// The new continuation Task. - /// The exception that is thrown when the + /// cref="Task">Task. + /// The new continuation Task. + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAny. /// public Task ContinueWhenAny(Task[] tasks, Func continuationFunction, @@ -1826,49 +1826,49 @@ public Task ContinueWhenAny(Task[] tasks, Func continuat } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The type of the result of the antecedent . /// The array of tasks from which to continue when one task completes. /// The function delegate to execute when one task in the /// array completes. - /// The new continuation . - /// The exception that is thrown when the + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. public Task ContinueWhenAny(Task[] tasks, Func, TResult> continuationFunction) { if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction); - return ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler); + return ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler); } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The type of the result of the antecedent . /// The array of tasks from which to continue when one task completes. /// The function delegate to execute when one task in the /// array completes. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The new continuation . - /// The exception that is thrown when the + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task ContinueWhenAny(Task[] tasks, Func, TResult> continuationFunction, @@ -1876,35 +1876,35 @@ public Task ContinueWhenAny(Task[ { if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction); - return ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler); + return ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler); } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The type of the result of the antecedent . /// The array of tasks from which to continue when one task completes. /// The function delegate to execute when one task in the /// array completes. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The new continuation . - /// The exception that is thrown when the + /// the created continuation Task. + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAny. /// public Task ContinueWhenAny(Task[] tasks, Func, TResult> continuationFunction, @@ -1912,45 +1912,45 @@ public Task ContinueWhenAny(Task[ { if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction); - return ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler); + return ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler); } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The type of the result of the antecedent . /// The array of tasks from which to continue when one task completes. /// The function delegate to execute when one task in the /// array completes. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The TaskScheduler + /// the created continuation Task. + /// The TaskScheduler /// that is used to schedule the created continuation . - /// The new continuation . - /// The exception that is thrown when the + /// cref="Task{TResult}"/>. + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAny. /// public Task ContinueWhenAny(Task[] tasks, Func, TResult> continuationFunction, @@ -1958,7 +1958,7 @@ public Task ContinueWhenAny(Task[ { if (continuationFunction == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.continuationFunction); - return ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler); + return ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler); } // Core implementation of ContinueWhenAny, non-generic version @@ -2039,14 +2039,14 @@ internal static Task ContinueWhenAnyImpl(Task( + return starter.ContinueWith( GenericDelegateCache.CWAnyFuncDelegate, continuationFunction, scheduler, cancellationToken, continuationOptions); } else { Debug.Assert(continuationAction != null); - return starter.ContinueWith( + return starter.ContinueWith( GenericDelegateCache.CWAnyActionDelegate, continuationAction, scheduler, cancellationToken, continuationOptions); } 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 b865b7763debd3..22621aa85e26b7 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 @@ -73,7 +73,7 @@ public enum TaskStatus /// /// instances may be created in a variety of ways. The most common approach is by /// using the Task type's property to retrieve a instance that can be used to create tasks for several + /// cref="TaskFactory"/> instance that can be used to create tasks for several /// purposes. For example, to create a that runs an action, the factory's StartNew /// method may be used: /// @@ -96,7 +96,7 @@ public enum TaskStatus /// and may be used from multiple threads concurrently. /// /// - /// For operations that return values, the class + /// For operations that return values, the class /// should be used. /// /// @@ -340,7 +340,7 @@ internal Task(object? state, TaskCreationOptions creationOptions, bool promiseSt // Only set a parent if AttachedToParent is specified. if ((creationOptions & TaskCreationOptions.AttachedToParent) != 0) { - Task? parent = Task.InternalCurrent; + Task? parent = InternalCurrent; if (parent != null) { EnsureContingentPropertiesInitializedUnsafe().m_parent = parent; @@ -354,20 +354,20 @@ internal Task(object? state, TaskCreationOptions creationOptions, bool promiseSt /// Initializes a new with the specified action. /// /// The delegate that represents the code to execute in the Task. - /// The argument is null. + /// The argument is null. public Task(Action action) : this(action, null, null, default, TaskCreationOptions.None, InternalTaskOptions.None, null) { } /// - /// Initializes a new with the specified action and CancellationToken. + /// Initializes a new with the specified action and CancellationToken. /// /// The delegate that represents the code to execute in the Task. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new Task. - /// The argument is null. - /// The provided CancellationToken + /// The argument is null. + /// The provided CancellationToken /// has already been disposed. /// public Task(Action action, CancellationToken cancellationToken) @@ -380,18 +380,18 @@ public Task(Action action, CancellationToken cancellationToken) /// /// The delegate that represents the code to execute in the task. /// - /// The TaskCreationOptions used to + /// The TaskCreationOptions used to /// customize the Task's behavior. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for . + /// cref="TaskCreationOptions"/>. /// public Task(Action action, TaskCreationOptions creationOptions) - : this(action, null, Task.InternalCurrentIfAttached(creationOptions), default, creationOptions, InternalTaskOptions.None, null) + : this(action, null, InternalCurrentIfAttached(creationOptions), default, creationOptions, InternalTaskOptions.None, null) { } @@ -401,21 +401,21 @@ public Task(Action action, TaskCreationOptions creationOptions) /// The delegate that represents the code to execute in the task. /// The that will be assigned to the new task. /// - /// The TaskCreationOptions used to + /// The TaskCreationOptions used to /// customize the Task's behavior. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for . + /// cref="TaskCreationOptions"/>. /// - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions) - : this(action, null, Task.InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null) + : this(action, null, InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null) { } @@ -424,7 +424,7 @@ public Task(Action action, CancellationToken cancellationToken, TaskCreationOpti /// /// The delegate that represents the code to execute in the task. /// An object representing data to be used by the action. - /// + /// /// The argument is null. /// public Task(Action action, object? state) @@ -438,10 +438,10 @@ public Task(Action action, object? state) /// The delegate that represents the code to execute in the task. /// An object representing data to be used by the action. /// The that will be assigned to the new task. - /// + /// /// The argument is null. /// - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task(Action action, object? state, CancellationToken cancellationToken) @@ -455,18 +455,18 @@ public Task(Action action, object? state, CancellationToken cancellatio /// The delegate that represents the code to execute in the task. /// An object representing data to be used by the action. /// - /// The TaskCreationOptions used to + /// The TaskCreationOptions used to /// customize the Task's behavior. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for . + /// cref="TaskCreationOptions"/>. /// public Task(Action action, object? state, TaskCreationOptions creationOptions) - : this(action, state, Task.InternalCurrentIfAttached(creationOptions), default, creationOptions, InternalTaskOptions.None, null) + : this(action, state, InternalCurrentIfAttached(creationOptions), default, creationOptions, InternalTaskOptions.None, null) { } @@ -477,21 +477,21 @@ public Task(Action action, object? state, TaskCreationOptions creationO /// An object representing data to be used by the action. /// The that will be assigned to the new task. /// - /// The TaskCreationOptions used to + /// The TaskCreationOptions used to /// customize the Task's behavior. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for . + /// cref="TaskCreationOptions"/>. /// - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task(Action action, object? state, CancellationToken cancellationToken, TaskCreationOptions creationOptions) - : this(action, state, Task.InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null) + : this(action, state, InternalCurrentIfAttached(creationOptions), cancellationToken, creationOptions, InternalTaskOptions.None, null) { } @@ -856,7 +856,7 @@ internal void FireTaskScheduledIfNeeded(TaskScheduler ts) if (TplEventSource.Log.IsEnabled()) { - Task? currentTask = Task.InternalCurrent; + Task? currentTask = InternalCurrent; Task? parentTask = m_contingentProperties?.m_parent; TplEventSource.Log.TaskScheduled(ts.Id, currentTask == null ? 0 : currentTask.Id, this.Id, parentTask == null ? 0 : parentTask.Id, (int)this.Options); @@ -874,7 +874,7 @@ internal void FireTaskScheduledIfNeeded(TaskScheduler ts) /// internal void AddNewChild() { - Debug.Assert(Task.InternalCurrent == this, "Task.AddNewChild(): Called from an external context"); + Debug.Assert(InternalCurrent == this, "Task.AddNewChild(): Called from an external context"); ContingentProperties props = EnsureContingentPropertiesInitialized(); @@ -895,7 +895,7 @@ internal void AddNewChild() // We need to subtract that child from m_completionCountdown, or the parent will never complete. internal void DisregardChild() { - Debug.Assert(Task.InternalCurrent == this, "Task.DisregardChild(): Called from an external context"); + Debug.Assert(InternalCurrent == this, "Task.DisregardChild(): Called from an external context"); ContingentProperties props = EnsureContingentPropertiesInitialized(); Debug.Assert(props.m_completionCountdown >= 2, "Task.DisregardChild(): Expected parent count to be >= 2"); @@ -904,7 +904,7 @@ internal void DisregardChild() /// /// Starts the , scheduling it for execution to the current TaskScheduler. + /// cref="TaskScheduler">TaskScheduler. /// /// /// A task may only be started and run only once. Any attempts to schedule a task a second time @@ -922,14 +922,14 @@ public void Start() /// /// Starts the , scheduling it for execution to the specified TaskScheduler. + /// cref="TaskScheduler">TaskScheduler. /// /// /// A task may only be started and run only once. Any attempts to schedule a task a second time will /// result in an exception. /// /// - /// The TaskScheduler with which to associate + /// The TaskScheduler with which to associate /// and execute this task. /// /// @@ -978,7 +978,7 @@ public void Start(TaskScheduler scheduler) /// /// Runs the synchronously on the current TaskScheduler. + /// cref="TaskScheduler">TaskScheduler. /// /// /// @@ -987,7 +987,7 @@ public void Start(TaskScheduler scheduler) /// /// /// Tasks executed with will be associated with the current TaskScheduler. + /// cref="TaskScheduler">TaskScheduler. /// /// /// If the target scheduler does not support running this Task on the current thread, the Task will @@ -1007,7 +1007,7 @@ public void RunSynchronously() /// /// Runs the synchronously on the scheduler provided. + /// cref="TaskScheduler">scheduler provided. /// /// /// @@ -1237,14 +1237,14 @@ public static int? CurrentId } /// - /// Gets the Exception that caused the Exception that caused the Task to end prematurely. If the Task completed successfully or has not yet thrown any /// exceptions, this will return null. /// /// /// Tasks that throw unhandled exceptions store the resulting exception and propagate it wrapped in a - /// in calls to Wait + /// in calls to Wait /// or in accesses to the property. Any exceptions not observed by the time /// the Task instance is garbage collected will be propagated on the finalizer thread. /// @@ -1267,7 +1267,7 @@ public AggregateException? Exception } /// - /// Gets the TaskStatus of this Task. + /// Gets the TaskStatus of this Task. /// public TaskStatus Status { @@ -1301,8 +1301,8 @@ public TaskStatus Status /// A Task will complete in Canceled state either if its CancellationToken /// was marked for cancellation before the task started executing, or if the task acknowledged the cancellation request on /// its already signaled CancellationToken by throwing an - /// OperationCanceledException that bears the same - /// CancellationToken. + /// OperationCanceledException that bears the same + /// CancellationToken. /// public bool IsCanceled => // Return true if canceled bit is set and faulted bit is not set @@ -1371,9 +1371,9 @@ internal CancellationToken CancellationToken /// /// /// will return true when the Task is in one of the three - /// final states: RanToCompletion, - /// Faulted, or - /// Canceled. + /// final states: RanToCompletion, + /// Faulted, or + /// Canceled. /// public bool IsCompleted { @@ -1394,7 +1394,7 @@ private static bool IsCompletedMethod(int flags) public bool IsCompletedSuccessfully => (m_stateFlags & (int)TaskStateFlags.CompletedMask) == (int)TaskStateFlags.RanToCompletion; /// - /// Gets the TaskCreationOptions used + /// Gets the TaskCreationOptions used /// to create this task. /// public TaskCreationOptions CreationOptions => Options & (TaskCreationOptions)(~InternalTaskOptions.InternalOptionsMask); @@ -1412,7 +1412,7 @@ internal void SpinUntilCompleted() } /// - /// Gets a that can be used to wait for the task to + /// Gets a that can be used to wait for the task to /// complete. /// /// @@ -1420,7 +1420,7 @@ internal void SpinUntilCompleted() /// should be preferred over using for similar /// functionality. /// - /// + /// /// The has been disposed. /// WaitHandle IAsyncResult.AsyncWaitHandle @@ -1460,7 +1460,7 @@ WaitHandle IAsyncResult.AsyncWaitHandle /// /// /// The factory returned from is a default instance - /// of , as would result from using + /// of , as would result from using /// the default constructor on TaskFactory. /// public static TaskFactory Factory { get; } = new TaskFactory(); @@ -1519,7 +1519,7 @@ internal bool ExceptionRecorded /// /// /// If is true, the Task's will be equal to - /// TaskStatus.Faulted, and its + /// TaskStatus.Faulted, and its /// property will be non-null. /// [MemberNotNullWhen(true, nameof(Exception))] @@ -1569,15 +1569,15 @@ internal ExecutionContext? CapturedContext /// /// Unlike most of the members of , this method is not thread-safe. /// Also, may only be called on a that is in one of - /// the final states: RanToCompletion, - /// Faulted, or - /// Canceled. + /// the final states: RanToCompletion, + /// Faulted, or + /// Canceled. /// - /// + /// /// The exception that is thrown if the is not in - /// one of the final states: RanToCompletion, - /// Faulted, or - /// Canceled. + /// one of the final states: RanToCompletion, + /// Faulted, or + /// Canceled. /// public void Dispose() { @@ -1948,7 +1948,7 @@ internal void UpdateExceptionObservedStatus() if ((parent != null) && ((Options & TaskCreationOptions.AttachedToParent) != 0) && ((parent.CreationOptions & TaskCreationOptions.DenyChildAttach) == 0) - && Task.InternalCurrent == parent) + && InternalCurrent == parent) { m_stateFlags |= (int)TaskStateFlags.ExceptionObservedByParent; } @@ -2438,34 +2438,50 @@ private void HandleException(Exception unhandledException) } #region Await Support - /// Gets an awaiter used to await this . + /// Gets an awaiter used to await this . /// An awaiter instance. public TaskAwaiter GetAwaiter() { return new TaskAwaiter(this); } - /// Configures an awaiter used to await this . + /// Configures an awaiter used to await this . /// /// true to attempt to marshal the continuation back to the original context captured; otherwise, false. /// /// An object used to await this task. public ConfiguredTaskAwaitable ConfigureAwait(bool continueOnCapturedContext) { - return new ConfiguredTaskAwaitable(this, continueOnCapturedContext); + return new ConfiguredTaskAwaitable(this, continueOnCapturedContext ? ConfigureAwaitOptions.ContinueOnCapturedContext : ConfigureAwaitOptions.None); + } + + /// Configures an awaiter used to await this . + /// Options used to configure how awaits on this task are performed. + /// An object used to await this task. + /// The argument specifies an invalid value. + public ConfiguredTaskAwaitable ConfigureAwait(ConfigureAwaitOptions options) + { + if ((options & ~(ConfigureAwaitOptions.ContinueOnCapturedContext | + ConfigureAwaitOptions.SuppressThrowing | + ConfigureAwaitOptions.ForceYielding)) != 0) + { + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.options); + } + + return new ConfiguredTaskAwaitable(this, options); } /// - /// Sets a continuation onto the . + /// Sets a continuation onto the . /// The continuation is scheduled to run in the current synchronization context is one exists, /// otherwise in the current task scheduler. /// - /// The action to invoke when the has completed. + /// The action to invoke when the has completed. /// /// true to attempt to marshal the continuation back to the original context captured; otherwise, false. /// /// Whether to flow ExecutionContext across the await. - /// The awaiter was not properly initialized. + /// The awaiter was not properly initialized. internal void SetContinuationForAwait( Action continuationAction, bool continueOnCapturedContext, bool flowExecutionContext) { @@ -2474,7 +2490,7 @@ internal void SetContinuationForAwait( // Create the best AwaitTaskContinuation object given the request. // If this remains null by the end of the function, we can use the // continuationAction directly without wrapping it. - TaskContinuation? tc = null; + TaskContinuation? tc; // If the user wants the continuation to run on the current "context" if there is one... if (continueOnCapturedContext) @@ -2485,24 +2501,22 @@ internal void SetContinuationForAwait( // then ignore it. This helps with performance by avoiding unnecessary posts and queueing // of work items, but more so it ensures that if code happens to publish the default context // as current, it won't prevent usage of a current task scheduler if there is one. - SynchronizationContext? syncCtx = SynchronizationContext.Current; - if (syncCtx != null && syncCtx.GetType() != typeof(SynchronizationContext)) + if (SynchronizationContext.Current is SynchronizationContext syncCtx && syncCtx.GetType() != typeof(SynchronizationContext)) { tc = new SynchronizationContextAwaitTaskContinuation(syncCtx, continuationAction, flowExecutionContext); + goto HaveTaskContinuation; } - else + + // If there was no SynchronizationContext, then try for the current scheduler. + // We only care about it if it's not the default. + if (TaskScheduler.InternalCurrent is TaskScheduler scheduler && scheduler != TaskScheduler.Default) { - // If there was no SynchronizationContext, then try for the current scheduler. - // We only care about it if it's not the default. - TaskScheduler? scheduler = TaskScheduler.InternalCurrent; - if (scheduler != null && scheduler != TaskScheduler.Default) - { - tc = new TaskSchedulerAwaitTaskContinuation(scheduler, continuationAction, flowExecutionContext); - } + tc = new TaskSchedulerAwaitTaskContinuation(scheduler, continuationAction, flowExecutionContext); + goto HaveTaskContinuation; } } - if (tc == null && flowExecutionContext) + if (flowExecutionContext) { // We're targeting the default scheduler, so we can use the faster path // that assumes the default, and thus we don't need to store it. If we're flowing @@ -2510,34 +2524,36 @@ internal void SetContinuationForAwait( // Otherwise, we're targeting the default scheduler and we don't need to flow ExecutionContext, so // we don't actually need a continuation object. We can just store/queue the action itself. tc = new AwaitTaskContinuation(continuationAction, flowExecutionContext: true); + goto HaveTaskContinuation; } // Now register the continuation, and if we couldn't register it because the task is already completing, // process the continuation directly (in which case make sure we schedule the continuation // rather than inlining it, the latter of which could result in a rare but possible stack overflow). - if (tc != null) + Debug.Assert(!flowExecutionContext, "We already determined we're not required to flow context."); + if (!AddTaskContinuation(continuationAction, addBeforeOthers: false)) { - if (!AddTaskContinuation(tc, addBeforeOthers: false)) - tc.Run(this, canInlineContinuationTask: false); + AwaitTaskContinuation.UnsafeScheduleAction(continuationAction, this); } - else + return; + + HaveTaskContinuation: + if (!AddTaskContinuation(tc, addBeforeOthers: false)) { - Debug.Assert(!flowExecutionContext, "We already determined we're not required to flow context."); - if (!AddTaskContinuation(continuationAction, addBeforeOthers: false)) - AwaitTaskContinuation.UnsafeScheduleAction(continuationAction, this); + tc.Run(this, canInlineContinuationTask: false); } } /// - /// Sets a continuation onto the . + /// Sets a continuation onto the . /// The continuation is scheduled to run in the current synchronization context is one exists, /// otherwise in the current task scheduler. /// - /// The action to invoke when the has completed. + /// The action to invoke when the has completed. /// /// true to attempt to marshal the continuation back to the original context captured; otherwise, false. /// - /// The awaiter was not properly initialized. + /// The awaiter was not properly initialized. internal void UnsafeSetContinuationForAwait(IAsyncStateMachineBox stateMachineBox, bool continueOnCapturedContext) { Debug.Assert(stateMachineBox != null); @@ -2549,32 +2565,25 @@ internal void UnsafeSetContinuationForAwait(IAsyncStateMachineBox stateMachineBo // method unless you've checked that TplEventSource.Log.IsEnabled() is false (if it becomes true after // the check, that's fine, and a natural race condition that's unavoidable). + // Create the best AwaitTaskContinuation object given the request. + // If this remains null by the end of the function, we can use the + // continuationAction directly without wrapping it. + TaskContinuation? tc; + // If the caller wants to continue on the current context/scheduler and there is one, // fall back to using the state machine's delegate. if (continueOnCapturedContext) { - SynchronizationContext? syncCtx = SynchronizationContext.Current; - if (syncCtx != null && syncCtx.GetType() != typeof(SynchronizationContext)) + if (SynchronizationContext.Current is SynchronizationContext syncCtx && syncCtx.GetType() != typeof(SynchronizationContext)) { - var tc = new SynchronizationContextAwaitTaskContinuation(syncCtx, stateMachineBox.MoveNextAction, flowExecutionContext: false); - if (!AddTaskContinuation(tc, addBeforeOthers: false)) - { - tc.Run(this, canInlineContinuationTask: false); - } - return; + tc = new SynchronizationContextAwaitTaskContinuation(syncCtx, stateMachineBox.MoveNextAction, flowExecutionContext: false); + goto HaveTaskContinuation; } - else + + if (TaskScheduler.InternalCurrent is TaskScheduler scheduler && scheduler != TaskScheduler.Default) { - TaskScheduler? scheduler = TaskScheduler.InternalCurrent; - if (scheduler != null && scheduler != TaskScheduler.Default) - { - var tc = new TaskSchedulerAwaitTaskContinuation(scheduler, stateMachineBox.MoveNextAction, flowExecutionContext: false); - if (!AddTaskContinuation(tc, addBeforeOthers: false)) - { - tc.Run(this, canInlineContinuationTask: false); - } - return; - } + tc = new TaskSchedulerAwaitTaskContinuation(scheduler, stateMachineBox.MoveNextAction, flowExecutionContext: false); + goto HaveTaskContinuation; } } @@ -2584,6 +2593,13 @@ internal void UnsafeSetContinuationForAwait(IAsyncStateMachineBox stateMachineBo { ThreadPool.UnsafeQueueUserWorkItemInternal(stateMachineBox, preferLocal: true); } + return; + + HaveTaskContinuation: + if (!AddTaskContinuation(tc, addBeforeOthers: false)) + { + tc.Run(this, canInlineContinuationTask: false); + } } /// Creates an awaitable that asynchronously yields back to the current context when awaited. @@ -2601,7 +2617,7 @@ public static YieldAwaitable Yield() /// /// Waits for the to complete execution. /// - /// + /// /// The was canceled -or- an exception was thrown during /// the execution of the . /// @@ -2621,17 +2637,17 @@ public void Wait() /// Waits for the to complete execution. /// /// - /// A that represents the number of milliseconds to wait, or a that represents -1 milliseconds to wait indefinitely. + /// A that represents the number of milliseconds to wait, or a that represents -1 milliseconds to wait indefinitely. /// /// /// true if the completed execution within the allotted time; otherwise, false. /// - /// + /// /// The was canceled -or- an exception was thrown during the execution of the . /// - /// + /// /// is a negative number other than -1 milliseconds, which represents an /// infinite time-out -or- timeout is greater than /// . @@ -2678,10 +2694,10 @@ public bool Wait(TimeSpan timeout, CancellationToken cancellationToken) /// /// A to observe while waiting for the task to complete. /// - /// + /// /// The was canceled. /// - /// + /// /// The was canceled -or- an exception was thrown during the execution of the . /// @@ -2694,16 +2710,16 @@ public void Wait(CancellationToken cancellationToken) /// Waits for the to complete execution. /// /// - /// The number of milliseconds to wait, or (-1) to + /// The number of milliseconds to wait, or (-1) to /// wait indefinitely. /// true if the completed execution within the allotted time; otherwise, /// false. /// - /// + /// /// is a negative number other than -1, which represents an /// infinite time-out. /// - /// + /// /// The was canceled -or- an exception was thrown during the execution of the . /// @@ -2716,7 +2732,7 @@ public bool Wait(int millisecondsTimeout) /// Waits for the to complete execution. /// /// - /// The number of milliseconds to wait, or (-1) to + /// The number of milliseconds to wait, or (-1) to /// wait indefinitely. /// /// @@ -2725,15 +2741,15 @@ public bool Wait(int millisecondsTimeout) /// /// true if the completed execution within the allotted time; otherwise, false. /// - /// + /// /// The was canceled -or- an exception was thrown during the execution of the . /// - /// + /// /// is a negative number other than -1, which represents an /// infinite time-out. /// - /// + /// /// The was canceled. /// public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken) @@ -2788,7 +2804,7 @@ public bool Wait(int millisecondsTimeout, CancellationToken cancellationToken) /// The timeout after which the should be faulted with a if it hasn't otherwise completed. /// The with which to interpret . /// The representing the asynchronous wait. It may or may not be the same instance as the current instance. - /// The argument is null. + /// The argument is null. public Task WaitAsync(TimeSpan timeout, TimeProvider timeProvider) { ArgumentNullException.ThrowIfNull(timeProvider); @@ -2807,7 +2823,7 @@ public Task WaitAsync(TimeSpan timeout, CancellationToken cancellationToken) => /// The with which to interpret . /// The to monitor for a cancellation request. /// The representing the asynchronous wait. It may or may not be the same instance as the current instance. - /// The argument is null. + /// The argument is null. public Task WaitAsync(TimeSpan timeout, TimeProvider timeProvider, CancellationToken cancellationToken) { ArgumentNullException.ThrowIfNull(timeProvider); @@ -2965,7 +2981,7 @@ private bool InternalWaitCore(int millisecondsTimeout, CancellationToken cancell bool etwIsEnabled = log.IsEnabled(); if (etwIsEnabled) { - Task? currentTask = Task.InternalCurrent; + Task? currentTask = InternalCurrent; log.TaskWaitBegin( currentTask != null ? currentTask.m_taskScheduler!.Id : TaskScheduler.Default.Id, currentTask != null ? currentTask.Id : 0, this.Id, TplEventSource.TaskWaitBehavior.Synchronous, 0); @@ -2996,7 +3012,7 @@ private bool InternalWaitCore(int millisecondsTimeout, CancellationToken cancell // ETW event for Task Wait End if (etwIsEnabled) { - Task? currentTask = Task.InternalCurrent; + Task? currentTask = InternalCurrent; if (currentTask != null) { log.TaskWaitEnd(currentTask.m_taskScheduler!.Id, currentTask.Id, this.Id); @@ -3100,7 +3116,7 @@ private bool SpinThenBlockingWait(int millisecondsTimeout, CancellationToken can /// /// The timeout. /// true if the task is completed; otherwise, false. - /// The wait was canceled. + /// The wait was canceled. private bool SpinWait(int millisecondsTimeout) { if (IsCompleted) return true; @@ -3290,7 +3306,7 @@ internal void CancellationCleanupLogic() /// private void SetCancellationAcknowledged() { - Debug.Assert(this == Task.InternalCurrent, "SetCancellationAcknowledged() should only be called while this is still the current task"); + Debug.Assert(this == InternalCurrent, "SetCancellationAcknowledged() should only be called while this is still the current task"); Debug.Assert(IsCancellationRequested, "SetCancellationAcknowledged() should not be called if the task's CT wasn't signaled"); m_stateFlags |= (int)TaskStateFlags.CancellationAcknowledged; @@ -3600,7 +3616,7 @@ private static void LogFinishCompletionNotification() /// completed, whether it completes due to running to completion successfully, faulting due to an /// unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Action continuationAction) @@ -3622,7 +3638,7 @@ public Task ContinueWith(Action continuationAction) /// completed, whether it completes due to running to completion successfully, faulting due to an /// unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Action continuationAction, CancellationToken cancellationToken) @@ -3646,10 +3662,10 @@ public Task ContinueWith(Action continuationAction, CancellationToken canc /// completed, whether it completes due to running to completion successfully, faulting due to an /// unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Action continuationAction, TaskScheduler scheduler) @@ -3667,9 +3683,9 @@ public Task ContinueWith(Action continuationAction, TaskScheduler schedule /// /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such /// as OnlyOnCanceled, as + /// cref="TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled, as /// well as execution options, such as ExecuteSynchronously. + /// cref="TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously. /// /// A new continuation . /// @@ -3678,12 +3694,12 @@ public Task ContinueWith(Action continuationAction, TaskScheduler schedule /// name="continuationOptions"/> parameter are not met, the continuation task will be canceled /// instead of scheduled. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for TaskContinuationOptions. + /// cref="TaskContinuationOptions">TaskContinuationOptions. /// public Task ContinueWith(Action continuationAction, TaskContinuationOptions continuationOptions) { @@ -3700,9 +3716,9 @@ public Task ContinueWith(Action continuationAction, TaskContinuationOption /// /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such /// as OnlyOnCanceled, as + /// cref="TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled, as /// well as execution options, such as ExecuteSynchronously. + /// cref="TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously. /// /// The that will be assigned to the new continuation task. /// @@ -3715,14 +3731,14 @@ public Task ContinueWith(Action continuationAction, TaskContinuationOption /// completed. If the criteria specified through the parameter /// are not met, the continuation task will be canceled instead of scheduled. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for TaskContinuationOptions. + /// cref="TaskContinuationOptions">TaskContinuationOptions. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Action continuationAction, CancellationToken cancellationToken, @@ -3778,7 +3794,7 @@ private Task ContinueWith(Action continuationAction, TaskScheduler schedul /// completed, whether it completes due to running to completion successfully, faulting due to an /// unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Action continuationAction, object? state) @@ -3801,7 +3817,7 @@ public Task ContinueWith(Action continuationAction, object? state /// completed, whether it completes due to running to completion successfully, faulting due to an /// unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Action continuationAction, object? state, CancellationToken cancellationToken) @@ -3826,10 +3842,10 @@ public Task ContinueWith(Action continuationAction, object? state /// completed, whether it completes due to running to completion successfully, faulting due to an /// unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Action continuationAction, object? state, TaskScheduler scheduler) @@ -3848,9 +3864,9 @@ public Task ContinueWith(Action continuationAction, object? state /// /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such /// as OnlyOnCanceled, as + /// cref="TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled, as /// well as execution options, such as ExecuteSynchronously. + /// cref="TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously. /// /// A new continuation . /// @@ -3859,12 +3875,12 @@ public Task ContinueWith(Action continuationAction, object? state /// name="continuationOptions"/> parameter are not met, the continuation task will be canceled /// instead of scheduled. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for TaskContinuationOptions. + /// cref="TaskContinuationOptions">TaskContinuationOptions. /// public Task ContinueWith(Action continuationAction, object? state, TaskContinuationOptions continuationOptions) { @@ -3882,9 +3898,9 @@ public Task ContinueWith(Action continuationAction, object? state /// /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such /// as OnlyOnCanceled, as + /// cref="TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled, as /// well as execution options, such as ExecuteSynchronously. + /// cref="TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously. /// /// The that will be assigned to the new continuation task. /// @@ -3897,14 +3913,14 @@ public Task ContinueWith(Action continuationAction, object? state /// completed. If the criteria specified through the parameter /// are not met, the continuation task will be canceled instead of scheduled. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for TaskContinuationOptions. + /// cref="TaskContinuationOptions">TaskContinuationOptions. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Action continuationAction, object? state, CancellationToken cancellationToken, @@ -3963,12 +3979,12 @@ private Task ContinueWith(Action continuationAction, object? stat /// completed, whether it completes due to running to completion successfully, faulting due to an /// unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Func continuationFunction) { - return ContinueWith(continuationFunction, TaskScheduler.Current, default, + return ContinueWith(continuationFunction, TaskScheduler.Current, default, TaskContinuationOptions.None); } @@ -3989,15 +4005,15 @@ public Task ContinueWith(Func continuationFunct /// completed, whether it completes due to running to completion successfully, faulting due to an /// unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task ContinueWith(Func continuationFunction, CancellationToken cancellationToken) { - return ContinueWith(continuationFunction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None); + return ContinueWith(continuationFunction, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None); } /// @@ -4019,15 +4035,15 @@ public Task ContinueWith(Func continuationFunct /// completed, whether it completes due to running to completion successfully, faulting due to an /// unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Func continuationFunction, TaskScheduler scheduler) { - return ContinueWith(continuationFunction, scheduler, default, TaskContinuationOptions.None); + return ContinueWith(continuationFunction, scheduler, default, TaskContinuationOptions.None); } /// @@ -4043,9 +4059,9 @@ public Task ContinueWith(Func continuationFunct /// /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such /// as OnlyOnCanceled, as + /// cref="TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled, as /// well as execution options, such as ExecuteSynchronously. + /// cref="TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously. /// /// A new continuation . /// @@ -4054,16 +4070,16 @@ public Task ContinueWith(Func continuationFunct /// name="continuationOptions"/> parameter are not met, the continuation task will be canceled /// instead of scheduled. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for TaskContinuationOptions. + /// cref="TaskContinuationOptions">TaskContinuationOptions. /// public Task ContinueWith(Func continuationFunction, TaskContinuationOptions continuationOptions) { - return ContinueWith(continuationFunction, TaskScheduler.Current, default, continuationOptions); + return ContinueWith(continuationFunction, TaskScheduler.Current, default, continuationOptions); } /// @@ -4080,9 +4096,9 @@ public Task ContinueWith(Func continuationFunct /// /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such /// as OnlyOnCanceled, as + /// cref="TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled, as /// well as execution options, such as ExecuteSynchronously. + /// cref="TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously. /// /// /// The to associate with the continuation task and to use for its @@ -4094,23 +4110,23 @@ public Task ContinueWith(Func continuationFunct /// completed. If the criteria specified through the parameter /// are not met, the continuation task will be canceled instead of scheduled. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for TaskContinuationOptions. + /// cref="TaskContinuationOptions">TaskContinuationOptions. /// - /// + /// /// The argument is null. /// - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task ContinueWith(Func continuationFunction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { - return ContinueWith(continuationFunction, scheduler, cancellationToken, continuationOptions); + return ContinueWith(continuationFunction, scheduler, cancellationToken, continuationOptions); } // Same as the above overload, just with a stack mark parameter. @@ -4163,12 +4179,12 @@ private Task ContinueWith(Func continuationFunc /// completed, whether it completes due to running to completion successfully, faulting due to an /// unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Func continuationFunction, object? state) { - return ContinueWith(continuationFunction, state, TaskScheduler.Current, default, + return ContinueWith(continuationFunction, state, TaskScheduler.Current, default, TaskContinuationOptions.None); } @@ -4190,15 +4206,15 @@ public Task ContinueWith(Func continua /// completed, whether it completes due to running to completion successfully, faulting due to an /// unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task ContinueWith(Func continuationFunction, object? state, CancellationToken cancellationToken) { - return ContinueWith(continuationFunction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None); + return ContinueWith(continuationFunction, state, TaskScheduler.Current, cancellationToken, TaskContinuationOptions.None); } /// @@ -4221,15 +4237,15 @@ public Task ContinueWith(Func continua /// completed, whether it completes due to running to completion successfully, faulting due to an /// unhandled exception, or exiting out early due to being canceled. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument is null. /// public Task ContinueWith(Func continuationFunction, object? state, TaskScheduler scheduler) { - return ContinueWith(continuationFunction, state, scheduler, default, TaskContinuationOptions.None); + return ContinueWith(continuationFunction, state, scheduler, default, TaskContinuationOptions.None); } /// @@ -4246,9 +4262,9 @@ public Task ContinueWith(Func continua /// /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such /// as OnlyOnCanceled, as + /// cref="TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled, as /// well as execution options, such as ExecuteSynchronously. + /// cref="TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously. /// /// A new continuation . /// @@ -4257,16 +4273,16 @@ public Task ContinueWith(Func continua /// name="continuationOptions"/> parameter are not met, the continuation task will be canceled /// instead of scheduled. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for TaskContinuationOptions. + /// cref="TaskContinuationOptions">TaskContinuationOptions. /// public Task ContinueWith(Func continuationFunction, object? state, TaskContinuationOptions continuationOptions) { - return ContinueWith(continuationFunction, state, TaskScheduler.Current, default, continuationOptions); + return ContinueWith(continuationFunction, state, TaskScheduler.Current, default, continuationOptions); } /// @@ -4284,9 +4300,9 @@ public Task ContinueWith(Func continua /// /// Options for when the continuation is scheduled and how it behaves. This includes criteria, such /// as OnlyOnCanceled, as + /// cref="TaskContinuationOptions.OnlyOnCanceled">OnlyOnCanceled, as /// well as execution options, such as ExecuteSynchronously. + /// cref="TaskContinuationOptions.ExecuteSynchronously">ExecuteSynchronously. /// /// /// The to associate with the continuation task and to use for its @@ -4298,23 +4314,23 @@ public Task ContinueWith(Func continua /// completed. If the criteria specified through the parameter /// are not met, the continuation task will be canceled instead of scheduled. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument specifies an invalid value for TaskContinuationOptions. + /// cref="TaskContinuationOptions">TaskContinuationOptions. /// - /// + /// /// The argument is null. /// - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task ContinueWith(Func continuationFunction, object? state, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { - return ContinueWith(continuationFunction, state, scheduler, cancellationToken, continuationOptions); + return ContinueWith(continuationFunction, state, scheduler, cancellationToken, continuationOptions); } // Same as the above overload, just with a stack mark parameter. @@ -4474,7 +4490,7 @@ internal void ContinueWithCore(Task continuationTask, TplEventSource log = TplEventSource.Log; if (log.IsEnabled()) { - log.AwaitTaskContinuationScheduled(TaskScheduler.Current.Id, Task.CurrentId ?? 0, continuationTask.Id); + log.AwaitTaskContinuationScheduled(TaskScheduler.Current.Id, CurrentId ?? 0, continuationTask.Id); } } @@ -4637,13 +4653,13 @@ internal void RemoveContinuation(object continuationObject) // could be TaskCont /// /// An array of instances on which to wait. /// - /// + /// /// The argument is null. /// - /// + /// /// 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. /// @@ -4672,20 +4688,20 @@ public static void WaitAll(params Task[] tasks) /// An array of instances on which to wait. /// /// - /// A that represents the number of milliseconds to wait, or a that represents -1 milliseconds to wait indefinitely. + /// A that represents the number of milliseconds to wait, or a that represents -1 milliseconds to wait indefinitely. /// - /// + /// /// The argument is null. /// - /// + /// /// 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. /// - /// + /// /// is a negative number other than -1 milliseconds, which represents an /// infinite time-out -or- timeout is greater than /// . @@ -4711,21 +4727,21 @@ public static bool WaitAll(Task[] tasks, TimeSpan timeout) /// otherwise, false. /// /// - /// The number of milliseconds to wait, or (-1) to + /// The number of milliseconds to wait, or (-1) to /// wait indefinitely. /// An array of instances on which to wait. /// - /// + /// /// The argument is null. /// - /// + /// /// 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. /// - /// + /// /// is a negative number other than -1, which represents an /// infinite time-out. /// @@ -4745,17 +4761,17 @@ public static bool WaitAll(Task[] tasks, int millisecondsTimeout) /// /// A to observe while waiting for the tasks to complete. /// - /// + /// /// The argument is null. /// - /// + /// /// 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. /// - /// + /// /// The was canceled. /// [UnsupportedOSPlatform("browser")] @@ -4776,27 +4792,27 @@ public static void WaitAll(Task[] tasks, CancellationToken cancellationToken) /// An array of instances on which to wait. /// /// - /// The number of milliseconds to wait, or (-1) to + /// The number of milliseconds to wait, or (-1) to /// wait indefinitely. /// /// /// A to observe while waiting for the tasks to complete. /// - /// + /// /// The argument is null. /// - /// + /// /// 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. /// - /// + /// /// is a negative number other than -1, which represents an /// infinite time-out. /// - /// + /// /// The was canceled. /// [UnsupportedOSPlatform("browser")] @@ -5035,10 +5051,10 @@ internal static void AddExceptionsForCompletedTask(ref List? exceptio /// An array of instances on which to wait. /// /// The index of the completed task in the array argument. - /// + /// /// The argument is null. /// - /// + /// /// The argument contains a null element. /// [MethodImpl(MethodImplOptions.NoOptimization)] // this is needed for the parallel debugger @@ -5056,20 +5072,20 @@ public static int WaitAny(params Task[] tasks) /// An array of instances on which to wait. /// /// - /// A that represents the number of milliseconds to wait, or a that represents -1 milliseconds to wait indefinitely. + /// A that represents the number of milliseconds to wait, or a that represents -1 milliseconds to wait indefinitely. /// /// /// The index of the completed task in the array argument, or -1 if the /// timeout occurred. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument contains a null element. /// - /// + /// /// is a negative number other than -1 milliseconds, which represents an /// infinite time-out -or- timeout is greater than /// . @@ -5098,13 +5114,13 @@ public static int WaitAny(Task[] tasks, TimeSpan timeout) /// /// The index of the completed task in the array argument. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument contains a null element. /// - /// + /// /// The was canceled. /// [MethodImpl(MethodImplOptions.NoOptimization)] // this is needed for the parallel debugger @@ -5120,20 +5136,20 @@ public static int WaitAny(Task[] tasks, CancellationToken cancellationToken) /// An array of instances on which to wait. /// /// - /// The number of milliseconds to wait, or (-1) to + /// The number of milliseconds to wait, or (-1) to /// wait indefinitely. /// /// /// The index of the completed task in the array argument, or -1 if the /// timeout occurred. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument contains a null element. /// - /// + /// /// is a negative number other than -1, which represents an /// infinite time-out. /// @@ -5150,7 +5166,7 @@ public static int WaitAny(Task[] tasks, int millisecondsTimeout) /// An array of instances on which to wait. /// /// - /// The number of milliseconds to wait, or (-1) to + /// The number of milliseconds to wait, or (-1) to /// wait indefinitely. /// /// @@ -5160,17 +5176,17 @@ public static int WaitAny(Task[] tasks, int millisecondsTimeout) /// The index of the completed task in the array argument, or -1 if the /// timeout occurred. /// - /// + /// /// The argument is null. /// - /// + /// /// The argument contains a null element. /// - /// + /// /// is a negative number other than -1, which represents an /// infinite time-out. /// - /// + /// /// The was canceled. /// [MethodImpl(MethodImplOptions.NoOptimization)] // this is needed for the parallel debugger @@ -5382,12 +5398,12 @@ internal static Task FromCanceled(OperationCanceledException e /// /// The work to execute asynchronously /// A Task that represents the work queued to execute in the ThreadPool. - /// + /// /// The parameter was null. /// public static Task Run(Action action) { - return Task.InternalStartNew(null, action, null, default, TaskScheduler.Default, + return InternalStartNew(null, action, null, default, TaskScheduler.Default, TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None); } @@ -5397,15 +5413,15 @@ public static Task Run(Action action) /// The work to execute asynchronously /// A cancellation token that should be used to cancel the work /// A Task that represents the work queued to execute in the ThreadPool. - /// + /// /// The parameter was null. /// - /// + /// /// The CancellationTokenSource associated with was disposed. /// public static Task Run(Action action, CancellationToken cancellationToken) { - return Task.InternalStartNew(null, action, null, cancellationToken, TaskScheduler.Default, + return InternalStartNew(null, action, null, cancellationToken, TaskScheduler.Default, TaskCreationOptions.DenyChildAttach, InternalTaskOptions.None); } @@ -5414,7 +5430,7 @@ public static Task Run(Action action, CancellationToken cancellationToken) /// /// The work to execute asynchronously /// A Task(TResult) that represents the work queued to execute in the ThreadPool. - /// + /// /// The parameter was null. /// public static Task Run(Func function) @@ -5429,10 +5445,10 @@ public static Task Run(Func function) /// The work to execute asynchronously /// A cancellation token that should be used to cancel the work /// A Task(TResult) that represents the work queued to execute in the ThreadPool. - /// + /// /// The parameter was null. /// - /// + /// /// The CancellationTokenSource associated with was disposed. /// public static Task Run(Func function, CancellationToken cancellationToken) @@ -5447,7 +5463,7 @@ public static Task Run(Func function, CancellationTok /// /// The work to execute asynchronously /// A Task that represents a proxy for the Task returned by . - /// + /// /// The parameter was null. /// public static Task Run(Func function) @@ -5462,10 +5478,10 @@ public static Task Run(Func function) /// The work to execute asynchronously /// A cancellation token that should be used to cancel the work /// A Task that represents a proxy for the Task returned by . - /// + /// /// The parameter was null. /// - /// + /// /// The CancellationTokenSource associated with was disposed. /// public static Task Run(Func function, CancellationToken cancellationToken) @@ -5474,7 +5490,7 @@ public static Task Run(Func function, CancellationToken cancellationToken // Short-circuit if we are given a pre-canceled token if (cancellationToken.IsCancellationRequested) - return Task.FromCanceled(cancellationToken); + return FromCanceled(cancellationToken); // Kick off initial Task, which will call the user-supplied function and yield a Task. Task task1 = Task.Factory.StartNew(function, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); @@ -5493,7 +5509,7 @@ public static Task Run(Func function, CancellationToken cancellationToken /// The type of the result returned by the proxy Task. /// The work to execute asynchronously /// A Task(TResult) that represents a proxy for the Task(TResult) returned by . - /// + /// /// The parameter was null. /// public static Task Run(Func?> function) @@ -5509,7 +5525,7 @@ public static Task Run(Func?> function) /// The work to execute asynchronously /// A cancellation token that should be used to cancel the work /// A Task(TResult) that represents a proxy for the Task(TResult) returned by . - /// + /// /// The parameter was null. /// public static Task Run(Func?> function, CancellationToken cancellationToken) @@ -5518,7 +5534,7 @@ public static Task Run(Func?> function, Cancella // Short-circuit if we are given a pre-canceled token if (cancellationToken.IsCancellationRequested) - return Task.FromCanceled(cancellationToken); + return FromCanceled(cancellationToken); // Kick off initial Task, which will call the user-supplied function and yield a Task. Task?> task1 = Task?>.Factory.StartNew(function, cancellationToken, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default); @@ -5539,7 +5555,7 @@ public static Task Run(Func?> function, Cancella /// /// The time span to wait before completing the returned Task /// A Task that represents the time delay - /// + /// /// The is less than -1 or greater than the maximum allowed timer duration. /// /// @@ -5553,7 +5569,7 @@ public static Task Run(Func?> function, Cancella /// A task that represents the time delay. /// represents a negative time interval other than . /// 's property is greater than 4294967294. - /// The argument is null. + /// The argument is null. public static Task Delay(TimeSpan delay, TimeProvider timeProvider) => Delay(delay, timeProvider, default); /// @@ -5562,10 +5578,10 @@ public static Task Run(Func?> function, Cancella /// The time span to wait before completing the returned Task /// The cancellation token that will be checked prior to completing the returned Task /// A Task that represents the time delay - /// + /// /// The is less than -1 or greater than the maximum allowed timer duration. /// - /// + /// /// The associated /// with has already been disposed. /// @@ -5584,7 +5600,7 @@ public static Task Delay(TimeSpan delay, CancellationToken cancellationToken) => /// A task that represents the time delay. /// represents a negative time interval other than . /// 's property is greater than 4294967294. - /// The argument is null. + /// The argument is null. public static Task Delay(TimeSpan delay, TimeProvider timeProvider, CancellationToken cancellationToken) { ArgumentNullException.ThrowIfNull(timeProvider); @@ -5596,7 +5612,7 @@ public static Task Delay(TimeSpan delay, TimeProvider timeProvider, Cancellation /// /// The number of milliseconds to wait before completing the returned Task /// A Task that represents the time delay - /// + /// /// The is less than -1. /// /// @@ -5610,10 +5626,10 @@ public static Task Delay(TimeSpan delay, TimeProvider timeProvider, Cancellation /// The number of milliseconds to wait before completing the returned Task /// The cancellation token that will be checked prior to completing the returned Task /// A Task that represents the time delay - /// + /// /// The is less than -1. /// - /// + /// /// The associated /// with has already been disposed. /// @@ -5783,10 +5799,10 @@ protected override void Cleanup() /// state before it's returned to the caller. /// /// - /// + /// /// The argument was null. /// - /// + /// /// The collection contained a null task. /// public static Task WhenAll(IEnumerable tasks) @@ -5844,10 +5860,10 @@ public static Task WhenAll(IEnumerable tasks) /// state before it's returned to the caller. /// /// - /// + /// /// The argument was null. /// - /// + /// /// The array contained a null task. /// public static Task WhenAll(params Task[] tasks) @@ -5881,7 +5897,7 @@ public static Task WhenAll(params Task[] tasks) /// state before it's returned to the caller. /// /// - /// The array contained a null task. + /// The array contained a null task. internal static Task WhenAll(ReadOnlySpan tasks) => // TODO https://github.com/dotnet/runtime/issues/77873: Make this public. tasks.Length != 0 ? new WhenAllPromise(tasks) : CompletedTask; @@ -6084,10 +6100,10 @@ void HandleTask(Task task) /// state before it's returned to the caller. The returned TResult[] will be an array of 0 elements. /// /// - /// + /// /// The argument was null. /// - /// + /// /// The collection contained a null task. /// public static Task WhenAll(IEnumerable> tasks) @@ -6095,7 +6111,7 @@ public static Task WhenAll(IEnumerable> tasks) // Take a more efficient route if tasks is actually an array if (tasks is Task[] taskArray) { - return WhenAll(taskArray); + return WhenAll(taskArray); } // Skip a List allocation/copy if tasks is a collection @@ -6108,7 +6124,7 @@ public static Task WhenAll(IEnumerable> tasks) if (task == null) ThrowHelper.ThrowArgumentException(ExceptionResource.Task_MultiTaskContinuation_NullTask, ExceptionArgument.tasks); taskArray[index++] = task; } - return InternalWhenAll(taskArray); + return InternalWhenAll(taskArray); } // Do some argument checking and convert tasks into a List (later an array) @@ -6121,7 +6137,7 @@ public static Task WhenAll(IEnumerable> tasks) } // Delegate the rest to InternalWhenAll(). - return InternalWhenAll(taskList.ToArray()); + return InternalWhenAll(taskList.ToArray()); } /// @@ -6148,10 +6164,10 @@ public static Task WhenAll(IEnumerable> tasks) /// state before it's returned to the caller. The returned TResult[] will be an array of 0 elements. /// /// - /// + /// /// The argument was null. /// - /// + /// /// The array contained a null task. /// public static Task WhenAll(params Task[] tasks) @@ -6160,7 +6176,7 @@ public static Task WhenAll(params Task[] tasks) if (tasks == 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 + if (taskCount == 0) return InternalWhenAll(tasks); // small optimization in the case of an empty task array Task[] tasksCopy = new Task[taskCount]; for (int i = 0; i < taskCount; i++) @@ -6171,7 +6187,7 @@ public static Task WhenAll(params Task[] tasks) } // Delegate the rest to InternalWhenAll() - return InternalWhenAll(tasksCopy); + return InternalWhenAll(tasksCopy); } // Some common logic to support WhenAll methods @@ -6279,7 +6295,7 @@ public void Invoke(Task ignored) if (TplEventSource.Log.IsEnabled()) TplEventSource.Log.TraceOperationEnd(this.Id, AsyncCausalityStatus.Completed); - if (Task.s_asyncDebuggingEnabled) + if (s_asyncDebuggingEnabled) RemoveFromActiveTasks(this); TrySetResult(results); @@ -6310,10 +6326,10 @@ public void Invoke(Task ignored) /// 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 argument was null. /// - /// + /// /// The array contained a null task, or was empty. /// public static Task WhenAny(params Task[] tasks) @@ -6356,7 +6372,7 @@ public static Task WhenAny(params Task[] tasks) /// 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 or argument was null. /// public static Task WhenAny(Task task1, Task task2) @@ -6459,10 +6475,10 @@ public void Invoke(Task completingTask) /// 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 argument was null. /// - /// + /// /// The collection contained a null task, or was empty. /// public static Task WhenAny(IEnumerable tasks) @@ -6521,10 +6537,10 @@ public static Task WhenAny(IEnumerable tasks) /// 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 argument was null. /// - /// + /// /// The array contained a null task, or was empty. /// public static Task> WhenAny(params Task[] tasks) @@ -6554,7 +6570,7 @@ public static Task> WhenAny(params Task[] tasks) /// 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 or argument was null. /// public static Task> WhenAny(Task task1, Task task2) @@ -6577,10 +6593,10 @@ public static Task> WhenAny(Task task1, Task - /// + /// /// The argument was null. /// - /// + /// /// The collection contained a null task, or was empty. /// public static Task> WhenAny(IEnumerable> tasks) @@ -6723,7 +6739,7 @@ public enum TaskCreationOptions None = 0x0, /// - /// A hint to a TaskScheduler to schedule a + /// A hint to a TaskScheduler to schedule a /// task in as fair a manner as possible, meaning that tasks scheduled sooner will be more likely to /// be run sooner, and tasks scheduled later will be more likely to be run later. /// @@ -6731,7 +6747,7 @@ public enum TaskCreationOptions /// /// Specifies that a task will be a long-running, course-grained operation. It provides a hint to the - /// TaskScheduler that oversubscription may be + /// TaskScheduler that oversubscription may be /// warranted. /// LongRunning = 0x02, @@ -6807,14 +6823,14 @@ public enum TaskContinuationOptions /// Default = "Continue on any, no task options, run asynchronously" /// Specifies that the default behavior should be used. Continuations, by default, will /// be scheduled when the antecedent task completes, regardless of the task's final TaskStatus. + /// cref="TaskStatus">TaskStatus. /// None = 0, // These are identical to their meanings and values in TaskCreationOptions /// - /// A hint to a TaskScheduler to schedule a + /// A hint to a TaskScheduler to schedule a /// task in as fair a manner as possible, meaning that tasks scheduled sooner will be more likely to /// be run sooner, and tasks scheduled later will be more likely to be run later. /// @@ -6822,7 +6838,7 @@ public enum TaskContinuationOptions /// /// Specifies that a task will be a long-running, coarse-grained operation. It provides - /// a hint to the TaskScheduler that + /// a hint to the TaskScheduler that /// oversubscription may be warranted. /// LongRunning = 0x02, @@ -7085,7 +7101,7 @@ private bool TrySetFromTask(Task task, bool lookForOce) if (TplEventSource.Log.IsEnabled()) TplEventSource.Log.TraceOperationEnd(this.Id, AsyncCausalityStatus.Completed); - if (Task.s_asyncDebuggingEnabled) + if (s_asyncDebuggingEnabled) RemoveFromActiveTasks(this); result = TrySetResult(task is Task taskTResult ? taskTResult.Result : default); diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskCanceledException.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskCanceledException.cs index c7fc558ea93f81..16c2c779da4eaa 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskCanceledException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskCanceledException.cs @@ -10,6 +10,7 @@ // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Threading.Tasks @@ -18,21 +19,21 @@ namespace System.Threading.Tasks /// Represents an exception used to communicate task cancellation. /// [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class TaskCanceledException : OperationCanceledException { [NonSerialized] private readonly Task? _canceledTask; // The task which has been canceled. /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public TaskCanceledException() : base(SR.TaskCanceledException_ctor_DefaultMessage) { } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class with a specified error message. /// /// The error message that explains the reason for the exception. @@ -41,7 +42,7 @@ public TaskCanceledException(string? message) : base(message) } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class with a specified error message and a reference to the inner exception that is the cause of /// this exception. /// @@ -52,7 +53,7 @@ public TaskCanceledException(string? message, Exception? innerException) : base( } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class with a specified error message, a reference to the inner exception that is the cause of /// this exception, and the that triggered the cancellation. /// @@ -64,8 +65,8 @@ public TaskCanceledException(string? message, Exception? innerException, Cancell } /// - /// Initializes a new instance of the class - /// with a reference to the that has been canceled. + /// Initializes a new instance of the class + /// with a reference to the that has been canceled. /// /// A task that has been canceled. public TaskCanceledException(Task? task) : @@ -75,11 +76,11 @@ public TaskCanceledException(Task? task) : } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class with serialized data. /// - /// The that holds the serialized object data about the exception being thrown. - /// The that contains contextual information about the source or destination. + /// The that holds the serialized object data about the exception being thrown. + /// The that contains contextual information about the source or destination. [Obsolete(Obsoletions.LegacyFormatterImplMessage, DiagnosticId = Obsoletions.LegacyFormatterImplDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] [EditorBrowsable(EditorBrowsableState.Never)] protected TaskCanceledException(SerializationInfo info, StreamingContext context) : base(info, context) @@ -91,7 +92,7 @@ protected TaskCanceledException(SerializationInfo info, StreamingContext context /// /// /// It is permissible for no Task to be associated with a - /// , in which case + /// , in which case /// this property will return null. /// public Task? Task => _canceledTask; diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskContinuation.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskContinuation.cs index 05576dae666fff..277a6e90765eda 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskContinuation.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskContinuation.cs @@ -13,7 +13,7 @@ internal sealed class ContinuationTaskFromTask : Task public ContinuationTaskFromTask( Task antecedent, Delegate action, object? state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) : - base(action, state, Task.InternalCurrentIfAttached(creationOptions), default, creationOptions, internalOptions, null) + base(action, state, InternalCurrentIfAttached(creationOptions), default, creationOptions, internalOptions, null) { Debug.Assert(action is Action || action is Action, "Invalid delegate type in ContinuationTaskFromTask"); @@ -59,7 +59,7 @@ internal sealed class ContinuationResultTaskFromTask : Task public ContinuationResultTaskFromTask( Task antecedent, Delegate function, object? state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) : - base(function, state, Task.InternalCurrentIfAttached(creationOptions), default, creationOptions, internalOptions, null) + base(function, state, InternalCurrentIfAttached(creationOptions), default, creationOptions, internalOptions, null) { Debug.Assert(function is Func || function is Func, "Invalid delegate type in ContinuationResultTaskFromTask"); @@ -105,7 +105,7 @@ internal sealed class ContinuationTaskFromResultTask : Task public ContinuationTaskFromResultTask( Task antecedent, Delegate action, object? state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) : - base(action, state, Task.InternalCurrentIfAttached(creationOptions), default, creationOptions, internalOptions, null) + base(action, state, InternalCurrentIfAttached(creationOptions), default, creationOptions, internalOptions, null) { Debug.Assert(action is Action> || action is Action, object?>, "Invalid delegate type in ContinuationTaskFromResultTask"); @@ -151,7 +151,7 @@ internal sealed class ContinuationResultTaskFromResultTask antecedent, Delegate function, object? state, TaskCreationOptions creationOptions, InternalTaskOptions internalOptions) : - base(function, state, Task.InternalCurrentIfAttached(creationOptions), default, creationOptions, internalOptions, null) + base(function, state, InternalCurrentIfAttached(creationOptions), default, creationOptions, internalOptions, null) { Debug.Assert(function is Func, TResult> || function is Func, object?, TResult>, "Invalid delegate type in ContinuationResultTaskFromResultTask"); @@ -434,9 +434,9 @@ private static Action GetActionLogDelegate(int continuationId, Action action) return () => { Guid activityId = TplEventSource.CreateGuidForTaskID(continuationId); - System.Diagnostics.Tracing.EventSource.SetCurrentThreadActivityId(activityId, out Guid savedActivityId); + Diagnostics.Tracing.EventSource.SetCurrentThreadActivityId(activityId, out Guid savedActivityId); try { action(); } - finally { System.Diagnostics.Tracing.EventSource.SetCurrentThreadActivityId(savedActivityId); } + finally { Diagnostics.Tracing.EventSource.SetCurrentThreadActivityId(savedActivityId); } }; } @@ -632,7 +632,7 @@ void IThreadPoolWorkItem.Execute() if (log.IsEnabled() && log.TasksSetActivityIds && m_continuationId != 0) { Guid activityId = TplEventSource.CreateGuidForTaskID(m_continuationId); - System.Diagnostics.Tracing.EventSource.SetCurrentThreadActivityId(activityId, out savedActivityId); + Diagnostics.Tracing.EventSource.SetCurrentThreadActivityId(activityId, out savedActivityId); } try { @@ -658,7 +658,7 @@ void IThreadPoolWorkItem.Execute() { if (log.IsEnabled() && log.TasksSetActivityIds && m_continuationId != 0) { - System.Diagnostics.Tracing.EventSource.SetCurrentThreadActivityId(savedActivityId); + Diagnostics.Tracing.EventSource.SetCurrentThreadActivityId(savedActivityId); } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskFactory.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskFactory.cs index d62e3c93753c4b..15ed14a929c0bd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskFactory.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskFactory.cs @@ -18,7 +18,7 @@ namespace System.Threading.Tasks { /// /// Provides support for creating and scheduling - /// Tasks. + /// Tasks. /// /// /// @@ -28,7 +28,7 @@ namespace System.Threading.Tasks /// /// /// A default instance of is available through the - /// Task.Factory property. + /// Task.Factory property. /// /// public class TaskFactory @@ -62,12 +62,12 @@ private TaskScheduler GetDefaultScheduler(Task? currTask) /// /// This constructor creates a instance with a default configuration. The /// property is initialized to - /// TaskCreationOptions.None, the + /// TaskCreationOptions.None, the /// property is initialized to TaskContinuationOptions.None, - /// and the TaskScheduler property is + /// cref="TaskContinuationOptions.None">TaskContinuationOptions.None, + /// and the TaskScheduler property is /// initialized to the current scheduler (see TaskScheduler.Current). + /// cref="TaskScheduler.Current">TaskScheduler.Current). /// public TaskFactory() { @@ -82,12 +82,12 @@ public TaskFactory() /// /// This constructor creates a instance with a default configuration. The /// property is initialized to - /// TaskCreationOptions.None, the + /// TaskCreationOptions.None, the /// property is initialized to TaskContinuationOptions.None, - /// and the TaskScheduler property is + /// cref="TaskContinuationOptions.None">TaskContinuationOptions.None, + /// and the TaskScheduler property is /// initialized to the current scheduler (see TaskScheduler.Current). + /// cref="TaskScheduler.Current">TaskScheduler.Current). /// public TaskFactory(CancellationToken cancellationToken) { @@ -98,20 +98,20 @@ public TaskFactory(CancellationToken cancellationToken) /// Initializes a instance with the specified configuration. /// /// - /// The + /// The /// TaskScheduler to use to schedule any tasks created with this TaskFactory. A null value /// indicates that the current TaskScheduler should be used. /// /// /// With this constructor, the /// property is initialized to - /// TaskCreationOptions.None, the + /// TaskCreationOptions.None, the /// property is initialized to TaskContinuationOptions.None, - /// and the TaskScheduler property is + /// cref="TaskContinuationOptions.None">TaskContinuationOptions.None, + /// and the TaskScheduler property is /// initialized to , unless it's null, in which case the property is /// initialized to the current scheduler (see TaskScheduler.Current). + /// cref="TaskScheduler.Current">TaskScheduler.Current). /// public TaskFactory(TaskScheduler? scheduler) // null means to use TaskScheduler.Current { @@ -122,14 +122,14 @@ public TaskFactory(TaskScheduler? scheduler) // null means to use TaskScheduler. /// Initializes a instance with the specified configuration. /// /// - /// The default + /// The default /// TaskCreationOptions to use when creating tasks with this TaskFactory. /// /// - /// The default + /// The default /// TaskContinuationOptions to use when creating continuation tasks with this TaskFactory. /// - /// + /// /// The exception that is thrown when the /// argument or the /// argument specifies an invalid value. @@ -140,9 +140,9 @@ public TaskFactory(TaskScheduler? scheduler) // null means to use TaskScheduler. /// the /// property is initialized to , and the TaskScheduler property is initialized to the + /// cref="TaskScheduler">TaskScheduler property is initialized to the /// current scheduler (see TaskScheduler.Current). + /// cref="TaskScheduler.Current">TaskScheduler.Current). /// public TaskFactory(TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions) { @@ -160,19 +160,19 @@ public TaskFactory(TaskCreationOptions creationOptions, TaskContinuationOptions /// to tasks created by this unless another CancellationToken is explicitly specified /// while calling the factory methods. /// - /// The default + /// The default /// TaskCreationOptions to use when creating tasks with this TaskFactory. /// /// - /// The default + /// The default /// TaskContinuationOptions to use when creating continuation tasks with this TaskFactory. /// /// - /// The default + /// The default /// TaskScheduler to use to schedule any Tasks created with this TaskFactory. A null value /// indicates that TaskScheduler.Current should be used. /// - /// + /// /// The exception that is thrown when the /// argument or the /// argumentspecifies an invalid value. @@ -183,10 +183,10 @@ public TaskFactory(TaskCreationOptions creationOptions, TaskContinuationOptions /// the /// property is initialized to , and the TaskScheduler property is initialized to + /// cref="TaskScheduler">TaskScheduler property is initialized to /// , unless it's null, in which case the property is initialized to the /// current scheduler (see TaskScheduler.Current). + /// cref="TaskScheduler.Current">TaskScheduler.Current). /// public TaskFactory(CancellationToken cancellationToken, TaskCreationOptions creationOptions, TaskContinuationOptions continuationOptions, TaskScheduler? scheduler) : this(creationOptions, continuationOptions) @@ -213,7 +213,7 @@ internal static void CheckCreationOptions(TaskCreationOptions creationOptions) /* Properties */ /// - /// Gets the default CancellationToken of this + /// Gets the default CancellationToken of this /// TaskFactory. /// /// @@ -224,19 +224,19 @@ internal static void CheckCreationOptions(TaskCreationOptions creationOptions) public CancellationToken CancellationToken => m_defaultCancellationToken; /// - /// Gets the TaskScheduler of this + /// Gets the TaskScheduler of this /// TaskFactory. /// /// /// This property returns the default scheduler for this factory. It will be used to schedule all /// tasks unless another scheduler is explicitly specified during calls to this factory's methods. - /// If null, TaskScheduler.Current + /// If null, TaskScheduler.Current /// will be used. /// public TaskScheduler? Scheduler => m_defaultScheduler; /// - /// Gets the TaskCreationOptions + /// Gets the TaskCreationOptions /// value of this TaskFactory. /// /// @@ -246,7 +246,7 @@ internal static void CheckCreationOptions(TaskCreationOptions creationOptions) public TaskCreationOptions CreationOptions => m_defaultCreationOptions; /// - /// Gets the TaskContinuationOptions + /// Gets the TaskContinuationOptions /// value of this TaskFactory. /// /// @@ -260,16 +260,16 @@ internal static void CheckCreationOptions(TaskCreationOptions creationOptions) // /// - /// Creates and starts a Task. + /// Creates and starts a Task. /// /// The action delegate to execute asynchronously. - /// The started Task. - /// The exception that is thrown when the + /// The started Task. + /// The exception that is thrown when the /// argument is null. /// /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors /// and then calling - /// Start to schedule it for execution. However, + /// Start to schedule it for execution. However, /// unless creation and scheduling must be separated, StartNew is the recommended /// approach for both simplicity and performance. /// @@ -281,20 +281,20 @@ public Task StartNew(Action action) } /// - /// Creates and starts a Task. + /// Creates and starts a Task. /// /// The action delegate to execute asynchronously. /// The that will be assigned to the new task. - /// The started Task. - /// The exception that is thrown when the + /// The started Task. + /// The exception that is thrown when the /// argument is null. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors /// and then calling - /// Start to schedule it for execution. However, + /// Start to schedule it for execution. However, /// unless creation and scheduling must be separated, StartNew is the recommended /// approach for both simplicity and performance. /// @@ -306,23 +306,23 @@ public Task StartNew(Action action, CancellationToken cancellationToken) } /// - /// Creates and starts a Task. + /// Creates and starts a Task. /// /// The action delegate to execute asynchronously. /// A TaskCreationOptions value that controls the behavior of the /// created - /// Task. - /// The started Task. - /// The exception that is thrown when the Task. + /// The started Task. + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. /// /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors and /// then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -334,34 +334,34 @@ public Task StartNew(Action action, TaskCreationOptions creationOptions) } /// - /// Creates and starts a Task. + /// Creates and starts a Task. /// /// The action delegate to execute asynchronously. /// The that will be assigned to the new /// A TaskCreationOptions value that controls the behavior of the /// created - /// Task. + /// Task. /// The TaskScheduler + /// cref="TaskScheduler">TaskScheduler /// that is used to schedule the created Task. - /// The started Task. - /// The exception that is thrown when the Task. + /// The started Task. + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors and /// then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -374,19 +374,19 @@ public Task StartNew(Action action, CancellationToken cancellationToken, TaskCre /// - /// Creates and starts a Task. + /// Creates and starts a Task. /// /// The action delegate to execute asynchronously. /// An object containing data to be used by the /// delegate. - /// The started Task. - /// The exception that is thrown when the The started Task. + /// The exception that is thrown when the /// argument is null. /// /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors and /// then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -399,23 +399,23 @@ public Task StartNew(Action action, object? state) /// - /// Creates and starts a Task. + /// Creates and starts a Task. /// /// The action delegate to execute asynchronously. /// An object containing data to be used by the /// delegate. /// The that will be assigned to the new - /// The started Task. - /// The exception that is thrown when the The started Task. + /// The exception that is thrown when the /// argument is null. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors and /// then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -427,25 +427,25 @@ public Task StartNew(Action action, object? state, CancellationToken ca } /// - /// Creates and starts a Task. + /// Creates and starts a Task. /// /// The action delegate to execute asynchronously. /// An object containing data to be used by the /// delegate. /// A TaskCreationOptions value that controls the behavior of the /// created - /// Task. - /// The started Task. - /// The exception that is thrown when the Task. + /// The started Task. + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. /// /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors and /// then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -457,7 +457,7 @@ public Task StartNew(Action action, object? state, TaskCreationOptions } /// - /// Creates and starts a Task. + /// Creates and starts a Task. /// /// The action delegate to execute asynchronously. /// An object containing data to be used by the @@ -465,28 +465,28 @@ public Task StartNew(Action action, object? state, TaskCreationOptions /// The that will be assigned to the new task. /// A TaskCreationOptions value that controls the behavior of the /// created - /// Task. + /// Task. /// The TaskScheduler + /// cref="TaskScheduler">TaskScheduler /// that is used to schedule the created Task. - /// The started Task. - /// The exception that is thrown when the Task. + /// The started Task. + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// /// Calling StartNew is functionally equivalent to creating a Task using one of its constructors and /// then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -499,21 +499,21 @@ public Task StartNew(Action action, object? state, CancellationToken ca } /// - /// Creates and starts a . + /// Creates and starts a . /// /// The type of the result available through the - /// Task. + /// Task. /// /// A function delegate that returns the future result to be available through - /// the . - /// The started . - /// The exception that is thrown when the . + /// The started . + /// The exception that is thrown when the /// argument is null. /// /// Calling StartNew is functionally equivalent to creating a using one /// of its constructors and then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -526,25 +526,25 @@ public Task StartNew(Func function) /// - /// Creates and starts a . + /// Creates and starts a . /// /// The type of the result available through the - /// Task. + /// Task. /// /// A function delegate that returns the future result to be available through - /// the . + /// the . /// The that will be assigned to the new - /// The started . - /// The exception that is thrown when the The started . + /// The exception that is thrown when the /// argument is null. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// /// Calling StartNew is functionally equivalent to creating a using one /// of its constructors and then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -556,27 +556,27 @@ public Task StartNew(Func function, CancellationToken } /// - /// Creates and starts a . + /// Creates and starts a . /// /// The type of the result available through the - /// Task. + /// Task. /// /// A function delegate that returns the future result to be available through - /// the . + /// the . /// A TaskCreationOptions value that controls the behavior of the /// created - /// . - /// The started . - /// The exception that is thrown when the . + /// The started . + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. /// /// Calling StartNew is functionally equivalent to creating a using one /// of its constructors and then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -588,38 +588,38 @@ public Task StartNew(Func function, TaskCreationOptio } /// - /// Creates and starts a . + /// Creates and starts a . /// /// The type of the result available through the - /// Task. + /// Task. /// /// A function delegate that returns the future result to be available through - /// the . + /// the . /// The that will be assigned to the new task. /// A TaskCreationOptions value that controls the behavior of the /// created - /// . + /// . /// The TaskScheduler - /// that is used to schedule the created + /// cref="TaskScheduler">TaskScheduler + /// that is used to schedule the created /// Task{TResult}. - /// The started . - /// The exception that is thrown when the The started . + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// /// Calling StartNew is functionally equivalent to creating a using one /// of its constructors and then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -631,23 +631,23 @@ public Task StartNew(Func function, CancellationToken } /// - /// Creates and starts a . + /// Creates and starts a . /// /// The type of the result available through the - /// Task. + /// Task. /// /// A function delegate that returns the future result to be available through - /// the . + /// the . /// An object containing data to be used by the /// delegate. - /// The started . - /// The exception that is thrown when the The started . + /// The exception that is thrown when the /// argument is null. /// /// Calling StartNew is functionally equivalent to creating a using one /// of its constructors and then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -660,27 +660,27 @@ public Task StartNew(Func function, object? /// - /// Creates and starts a . + /// Creates and starts a . /// /// The type of the result available through the - /// Task. + /// Task. /// /// A function delegate that returns the future result to be available through - /// the . + /// the . /// An object containing data to be used by the /// delegate. /// The that will be assigned to the new - /// The started . - /// The exception that is thrown when the The started . + /// The exception that is thrown when the /// argument is null. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// /// Calling StartNew is functionally equivalent to creating a using one /// of its constructors and then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -692,29 +692,29 @@ public Task StartNew(Func function, object? } /// - /// Creates and starts a . + /// Creates and starts a . /// /// The type of the result available through the - /// Task. + /// Task. /// /// A function delegate that returns the future result to be available through - /// the . + /// the . /// An object containing data to be used by the /// delegate. /// A TaskCreationOptions value that controls the behavior of the /// created - /// . - /// The started . - /// The exception that is thrown when the . + /// The started . + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. /// /// Calling StartNew is functionally equivalent to creating a using one /// of its constructors and then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -726,40 +726,40 @@ public Task StartNew(Func function, object? } /// - /// Creates and starts a . + /// Creates and starts a . /// /// The type of the result available through the - /// Task. + /// Task. /// /// A function delegate that returns the future result to be available through - /// the . + /// the . /// An object containing data to be used by the /// delegate. /// The that will be assigned to the new task. /// A TaskCreationOptions value that controls the behavior of the /// created - /// . + /// . /// The TaskScheduler - /// that is used to schedule the created + /// cref="TaskScheduler">TaskScheduler + /// that is used to schedule the created /// Task{TResult}. - /// The started . - /// The exception that is thrown when the The started . + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// /// Calling StartNew is functionally equivalent to creating a using one /// of its constructors and then calling - /// Start to schedule it for execution. + /// Start to schedule it for execution. /// However, unless creation and scheduling must be separated, StartNew is the recommended approach /// for both simplicity and performance. /// @@ -776,18 +776,18 @@ public Task StartNew(Func function, object? // /// - /// Creates a Task that executes an end method action - /// when a specified IAsyncResult completes. + /// Creates a Task that executes an end method action + /// when a specified IAsyncResult completes. /// /// The IAsyncResult whose completion should trigger the processing of the /// . /// The action delegate that processes the completed . - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// A Task that represents the asynchronous + /// A Task that represents the asynchronous /// operation. public Task FromAsync( IAsyncResult asyncResult, @@ -797,23 +797,23 @@ public Task FromAsync( } /// - /// Creates a Task that executes an end method action - /// when a specified IAsyncResult completes. + /// Creates a Task that executes an end method action + /// when a specified IAsyncResult completes. /// /// The IAsyncResult whose completion should trigger the processing of the /// . /// The action delegate that processes the completed . /// The TaskCreationOptions value that controls the behavior of the - /// created Task. - /// The exception that is thrown when the + /// created Task. + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// A Task that represents the asynchronous + /// A Task that represents the asynchronous /// operation. public Task FromAsync( IAsyncResult asyncResult, @@ -824,27 +824,27 @@ public Task FromAsync( } /// - /// Creates a Task that executes an end method action - /// when a specified IAsyncResult completes. + /// Creates a Task that executes an end method action + /// when a specified IAsyncResult completes. /// /// The IAsyncResult whose completion should trigger the processing of the /// . /// The action delegate that processes the completed . - /// The TaskScheduler + /// The TaskScheduler /// that is used to schedule the task that executes the end method. /// The TaskCreationOptions value that controls the behavior of the - /// created Task. - /// The exception that is thrown when the + /// created Task. + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// A Task that represents the asynchronous + /// A Task that represents the asynchronous /// operation. public Task FromAsync( IAsyncResult asyncResult, @@ -856,18 +856,18 @@ public Task FromAsync( } /// - /// Creates a Task that represents a pair of begin + /// Creates a Task that represents a pair of begin /// and end methods that conform to the Asynchronous Programming Model pattern. /// /// The delegate that begins the asynchronous operation. /// The delegate that ends the asynchronous operation. /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The created Task that represents the + /// The created Task that represents the /// asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -881,23 +881,23 @@ public Task FromAsync( } /// - /// Creates a Task that represents a pair of begin + /// Creates a Task that represents a pair of begin /// and end methods that conform to the Asynchronous Programming Model pattern. /// /// The delegate that begins the asynchronous operation. /// The delegate that ends the asynchronous operation. /// The TaskCreationOptions value that controls the behavior of the - /// created Task. + /// created Task. /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// The created Task that represents the + /// The created Task that represents the /// asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -910,7 +910,7 @@ public Task FromAsync( } /// - /// Creates a Task that represents a pair of begin + /// Creates a Task that represents a pair of begin /// and end methods that conform to the Asynchronous Programming Model pattern. /// /// The type of the first argument passed to the /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The created Task that represents the + /// The created Task that represents the /// asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -941,7 +941,7 @@ public Task FromAsync( } /// - /// Creates a Task that represents a pair of begin + /// Creates a Task that represents a pair of begin /// and end methods that conform to the Asynchronous Programming Model pattern. /// /// The type of the first argument passed to the ( /// The first argument passed to the /// delegate. /// The TaskCreationOptions value that controls the behavior of the - /// created Task. + /// created Task. /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// The created Task that represents the + /// The created Task that represents the /// asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -976,7 +976,7 @@ public Task FromAsync( } /// - /// Creates a Task that represents a pair of begin + /// Creates a Task that represents a pair of begin /// and end methods that conform to the Asynchronous Programming Model pattern. /// /// The type of the first argument passed to the ( /// delegate. /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The created Task that represents the + /// The created Task that represents the /// asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -1010,7 +1010,7 @@ public Task FromAsync( } /// - /// Creates a Task that represents a pair of begin + /// Creates a Task that represents a pair of begin /// and end methods that conform to the Asynchronous Programming Model pattern. /// /// The type of the first argument passed to the ( /// The second argument passed to the /// delegate. /// The TaskCreationOptions value that controls the behavior of the - /// created Task. + /// created Task. /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// The created Task that represents the + /// The created Task that represents the /// asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -1049,7 +1049,7 @@ public Task FromAsync( } /// - /// Creates a Task that represents a pair of begin + /// Creates a Task that represents a pair of begin /// and end methods that conform to the Asynchronous Programming Model pattern. /// /// The type of the first argument passed to the ( /// delegate. /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The created Task that represents the + /// The created Task that represents the /// asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -1087,7 +1087,7 @@ public Task FromAsync( } /// - /// Creates a Task that represents a pair of begin + /// Creates a Task that represents a pair of begin /// and end methods that conform to the Asynchronous Programming Model pattern. /// /// The type of the first argument passed to the ( /// The third argument passed to the /// delegate. /// The TaskCreationOptions value that controls the behavior of the - /// created Task. + /// created Task. /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// The created Task that represents the + /// The created Task that represents the /// asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -1126,7 +1126,7 @@ public Task FromAsync( Action endMethod, TArg1 arg1, TArg2 arg2, TArg3 arg3, object? state, TaskCreationOptions creationOptions) { - return TaskFactory.FromAsyncImpl(beginMethod, null, endMethod, arg1, arg2, arg3, state, creationOptions); + return TaskFactory.FromAsyncImpl(beginMethod, null, endMethod, arg1, arg2, arg3, state, creationOptions); } // @@ -1134,21 +1134,21 @@ public Task FromAsync( // /// - /// Creates a Task that executes an end - /// method function when a specified IAsyncResult completes. + /// Creates a Task that executes an end + /// method function when a specified IAsyncResult completes. /// /// The type of the result available through the - /// Task. + /// Task. /// /// The IAsyncResult whose completion should trigger the processing of the /// . /// The function delegate that processes the completed . - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// A Task that represents the + /// A Task that represents the /// asynchronous operation. public Task FromAsync( IAsyncResult asyncResult, Func endMethod) @@ -1157,26 +1157,26 @@ public Task FromAsync( } /// - /// Creates a Task that executes an end - /// method function when a specified IAsyncResult completes. + /// Creates a Task that executes an end + /// method function when a specified IAsyncResult completes. /// /// The type of the result available through the - /// Task. + /// Task. /// /// The IAsyncResult whose completion should trigger the processing of the /// . /// The function delegate that processes the completed . /// The TaskCreationOptions value that controls the behavior of the - /// created Task. - /// The exception that is thrown when the + /// created Task. + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// A Task that represents the + /// A Task that represents the /// asynchronous operation. public Task FromAsync( IAsyncResult asyncResult, Func endMethod, TaskCreationOptions creationOptions) @@ -1185,30 +1185,30 @@ public Task FromAsync( } /// - /// Creates a Task that executes an end - /// method function when a specified IAsyncResult completes. + /// Creates a Task that executes an end + /// method function when a specified IAsyncResult completes. /// /// The type of the result available through the - /// Task. + /// Task. /// /// The IAsyncResult whose completion should trigger the processing of the /// . /// The function delegate that processes the completed . - /// The TaskScheduler + /// The TaskScheduler /// that is used to schedule the task that executes the end method. /// The TaskCreationOptions value that controls the behavior of the - /// created Task. - /// The exception that is thrown when the + /// created Task. + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// A Task that represents the + /// A Task that represents the /// asynchronous operation. public Task FromAsync( IAsyncResult asyncResult, Func endMethod, TaskCreationOptions creationOptions, TaskScheduler scheduler) @@ -1217,21 +1217,21 @@ public Task FromAsync( } /// - /// Creates a Task that represents a pair of + /// Creates a Task that represents a pair of /// begin and end methods that conform to the Asynchronous Programming Model pattern. /// /// The type of the result available through the - /// Task. + /// Task. /// /// The delegate that begins the asynchronous operation. /// The delegate that ends the asynchronous operation. /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The created Task that + /// The created Task that /// represents the asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -1244,26 +1244,26 @@ public Task FromAsync( } /// - /// Creates a Task that represents a pair of + /// Creates a Task that represents a pair of /// begin and end methods that conform to the Asynchronous Programming Model pattern. /// /// The type of the result available through the - /// Task. + /// Task. /// /// The delegate that begins the asynchronous operation. /// The delegate that ends the asynchronous operation. /// The TaskCreationOptions value that controls the behavior of the - /// created Task. + /// created Task. /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// The created Task that + /// The created Task that /// represents the asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -1276,13 +1276,13 @@ public Task FromAsync( } /// - /// Creates a Task that represents a pair of + /// Creates a Task that represents a pair of /// begin and end methods that conform to the Asynchronous Programming Model pattern. /// /// The type of the first argument passed to the delegate. /// The type of the result available through the - /// Task. + /// Task. /// /// The delegate that begins the asynchronous operation. /// The delegate that ends the asynchronous operation. @@ -1290,11 +1290,11 @@ public Task FromAsync( /// delegate. /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The created Task that + /// The created Task that /// represents the asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -1307,30 +1307,30 @@ public Task FromAsync( } /// - /// Creates a Task that represents a pair of + /// Creates a Task that represents a pair of /// begin and end methods that conform to the Asynchronous Programming Model pattern. /// /// The type of the first argument passed to the delegate. /// The type of the result available through the - /// Task. + /// Task. /// /// The delegate that begins the asynchronous operation. /// The delegate that ends the asynchronous operation. /// The first argument passed to the /// delegate. /// The TaskCreationOptions value that controls the behavior of the - /// created Task. + /// created Task. /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// The created Task that + /// The created Task that /// represents the asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -1342,7 +1342,7 @@ public Task FromAsync(Func - /// Creates a Task that represents a pair of + /// Creates a Task that represents a pair of /// begin and end methods that conform to the Asynchronous Programming Model pattern. /// /// The type of the first argument passed to the FromAsync(FuncThe type of the second argument passed to /// delegate. /// The type of the result available through the - /// Task. + /// Task. /// /// The delegate that begins the asynchronous operation. /// The delegate that ends the asynchronous operation. @@ -1360,11 +1360,11 @@ public Task FromAsync(Func /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The created Task that + /// The created Task that /// represents the asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -1376,7 +1376,7 @@ public Task FromAsync(Func - /// Creates a Task that represents a pair of + /// Creates a Task that represents a pair of /// begin and end methods that conform to the Asynchronous Programming Model pattern. /// /// The type of the first argument passed to the FromAsync(FuncThe type of the second argument passed to /// delegate. /// The type of the result available through the - /// Task. + /// Task. /// /// The delegate that begins the asynchronous operation. /// The delegate that ends the asynchronous operation. @@ -1393,17 +1393,17 @@ public Task FromAsync(FuncThe second argument passed to the /// delegate. /// The TaskCreationOptions value that controls the behavior of the - /// created Task. + /// created Task. /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// The created Task that + /// The created Task that /// represents the asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -1416,7 +1416,7 @@ public Task FromAsync( } /// - /// Creates a Task that represents a pair of + /// Creates a Task that represents a pair of /// begin and end methods that conform to the Asynchronous Programming Model pattern. /// /// The type of the first argument passed to the FromAsync( /// The type of the third argument passed to /// delegate. /// The type of the result available through the - /// Task. + /// Task. /// /// The delegate that begins the asynchronous operation. /// The delegate that ends the asynchronous operation. @@ -1438,11 +1438,11 @@ public Task FromAsync( /// delegate. /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The created Task that + /// The created Task that /// represents the asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -1455,7 +1455,7 @@ public Task FromAsync( } /// - /// Creates a Task that represents a pair of + /// Creates a Task that represents a pair of /// begin and end methods that conform to the Asynchronous Programming Model pattern. /// /// The type of the first argument passed to the FromAsync( /// The type of the third argument passed to /// delegate. /// The type of the result available through the - /// Task. + /// Task. /// /// The delegate that begins the asynchronous operation. /// The delegate that ends the asynchronous operation. @@ -1476,17 +1476,17 @@ public Task FromAsync( /// The third argument passed to the /// delegate. /// The TaskCreationOptions value that controls the behavior of the - /// created Task. + /// created Task. /// An object containing data to be used by the /// delegate. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskCreationOptions /// value. - /// The created Task that + /// The created Task that /// represents the asynchronous operation. /// /// This method throws any exceptions thrown by the . @@ -1558,7 +1558,7 @@ internal CompleteOnCountdownPromise(Task[] tasksCopy) if (TplEventSource.Log.IsEnabled()) TplEventSource.Log.TraceOperationBegin(this.Id, "TaskFactory.ContinueWhenAll", 0); - if (Task.s_asyncDebuggingEnabled) + if (s_asyncDebuggingEnabled) AddToActiveTasks(this); } @@ -1573,7 +1573,7 @@ public void Invoke(Task completingTask) if (TplEventSource.Log.IsEnabled()) TplEventSource.Log.TraceOperationEnd(this.Id, AsyncCausalityStatus.Completed); - if (Task.s_asyncDebuggingEnabled) + if (s_asyncDebuggingEnabled) RemoveFromActiveTasks(this); TrySetResult(_tasks); @@ -1628,7 +1628,7 @@ internal CompleteOnCountdownPromise(Task[] tasksCopy) if (TplEventSource.Log.IsEnabled()) TplEventSource.Log.TraceOperationBegin(this.Id, "TaskFactory.ContinueWhenAll<>", 0); - if (Task.s_asyncDebuggingEnabled) + if (s_asyncDebuggingEnabled) AddToActiveTasks(this); } @@ -1643,7 +1643,7 @@ public void Invoke(Task completingTask) if (TplEventSource.Log.IsEnabled()) TplEventSource.Log.TraceOperationEnd(this.Id, AsyncCausalityStatus.Completed); - if (Task.s_asyncDebuggingEnabled) + if (s_asyncDebuggingEnabled) RemoveFromActiveTasks(this); TrySetResult(_tasks); @@ -1680,20 +1680,20 @@ internal static Task[]> CommonCWAllLogic(Task[] tasksCopy) } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The array of tasks from which to continue. /// The action delegate to execute when all tasks in /// the array have completed. - /// The new continuation Task. - /// The exception that is thrown when the + /// The new continuation Task. + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. public Task ContinueWhenAll(Task[] tasks, Action continuationAction) { @@ -1703,24 +1703,24 @@ public Task ContinueWhenAll(Task[] tasks, Action continuationAction) } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The array of tasks from which to continue. /// The action delegate to execute when all tasks in /// the array have completed. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The new continuation Task. - /// The exception that is thrown when the + /// The new continuation Task. + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task ContinueWhenAll(Task[] tasks, Action continuationAction, CancellationToken cancellationToken) @@ -1731,30 +1731,30 @@ public Task ContinueWhenAll(Task[] tasks, Action continuationAction, Can } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The array of tasks from which to continue. /// The action delegate to execute when all tasks in the array have completed. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The new continuation Task. - /// The exception that is thrown when the + /// the created continuation Task. + /// The new continuation Task. + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAll. /// public Task ContinueWhenAll(Task[] tasks, Action continuationAction, TaskContinuationOptions continuationOptions) @@ -1765,40 +1765,40 @@ public Task ContinueWhenAll(Task[] tasks, Action continuationAction, Tas } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The array of tasks from which to continue. /// The action delegate to execute when all tasks in the array have completed. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The TaskScheduler + /// the created continuation Task. + /// The TaskScheduler /// that is used to schedule the created continuation Task. - /// The new continuation Task. - /// The exception that is thrown when the + /// cref="Task">Task. + /// The new continuation Task. + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAll. /// public Task ContinueWhenAll(Task[] tasks, Action continuationAction, CancellationToken cancellationToken, @@ -1810,50 +1810,50 @@ public Task ContinueWhenAll(Task[] tasks, Action continuationAction, Can } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The type of the result of the antecedent . /// The array of tasks from which to continue. /// The action delegate to execute when all tasks in /// the array have completed. - /// The new continuation Task. - /// The exception that is thrown when the + /// The new continuation Task. + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. public Task ContinueWhenAll(Task[] tasks, Action[]> continuationAction) { ArgumentNullException.ThrowIfNull(continuationAction); - return TaskFactory.ContinueWhenAllImpl(tasks, null, continuationAction, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler); + return TaskFactory.ContinueWhenAllImpl(tasks, null, continuationAction, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler); } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The type of the result of the antecedent . /// The array of tasks from which to continue. /// The action delegate to execute when all tasks in /// the array have completed. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The new continuation Task. - /// The exception that is thrown when the + /// The new continuation Task. + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task ContinueWhenAll(Task[] tasks, Action[]> continuationAction, @@ -1861,35 +1861,35 @@ public Task ContinueWhenAll(Task[] tasks, { ArgumentNullException.ThrowIfNull(continuationAction); - return TaskFactory.ContinueWhenAllImpl(tasks, null, continuationAction, m_defaultContinuationOptions, cancellationToken, DefaultScheduler); + return TaskFactory.ContinueWhenAllImpl(tasks, null, continuationAction, m_defaultContinuationOptions, cancellationToken, DefaultScheduler); } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The type of the result of the antecedent . /// The array of tasks from which to continue. /// The action delegate to execute when all tasks in the array have completed. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The new continuation Task. - /// The exception that is thrown when the + /// the created continuation Task. + /// The new continuation Task. + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAll. /// public Task ContinueWhenAll(Task[] tasks, Action[]> continuationAction, @@ -1897,45 +1897,45 @@ public Task ContinueWhenAll(Task[] tasks, { ArgumentNullException.ThrowIfNull(continuationAction); - return TaskFactory.ContinueWhenAllImpl(tasks, null, continuationAction, continuationOptions, m_defaultCancellationToken, DefaultScheduler); + return TaskFactory.ContinueWhenAllImpl(tasks, null, continuationAction, continuationOptions, m_defaultCancellationToken, DefaultScheduler); } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The type of the result of the antecedent . /// The array of tasks from which to continue. /// The action delegate to execute when all tasks in the array have completed. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The TaskScheduler + /// the created continuation Task. + /// The TaskScheduler /// that is used to schedule the created continuation Task. - /// The new continuation Task. - /// The exception that is thrown when the + /// cref="Task">Task. + /// The new continuation Task. + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAll. /// public Task ContinueWhenAll(Task[] tasks, Action[]> continuationAction, @@ -1943,28 +1943,28 @@ public Task ContinueWhenAll(Task[] tasks, { ArgumentNullException.ThrowIfNull(continuationAction); - return TaskFactory.ContinueWhenAllImpl(tasks, null, continuationAction, continuationOptions, cancellationToken, scheduler); + return TaskFactory.ContinueWhenAllImpl(tasks, null, continuationAction, continuationOptions, cancellationToken, scheduler); } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The type of the result that is returned by the /// delegate and associated with the created . + /// cref="Task{TResult}"/>. /// The array of tasks from which to continue. /// The function delegate to execute when all tasks in the /// array have completed. - /// The new continuation . - /// The exception that is thrown when the + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. public Task ContinueWhenAll(Task[] tasks, Func continuationFunction) { @@ -1975,28 +1975,28 @@ public Task ContinueWhenAll(Task[] tasks, Func - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The type of the result that is returned by the /// delegate and associated with the created . + /// cref="Task{TResult}"/>. /// The array of tasks from which to continue. /// The function delegate to execute when all tasks in the /// array have completed. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The new continuation . - /// The exception that is thrown when the + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task ContinueWhenAll(Task[] tasks, Func continuationFunction, CancellationToken cancellationToken) @@ -2007,34 +2007,34 @@ public Task ContinueWhenAll(Task[] tasks, Func - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The type of the result that is returned by the /// delegate and associated with the created . + /// cref="Task{TResult}"/>. /// The array of tasks from which to continue. /// The function delegate to execute when all tasks in the /// array have completed. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The new continuation . - /// The exception that is thrown when the + /// the created continuation Task. + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAll. /// public Task ContinueWhenAll(Task[] tasks, Func continuationFunction, TaskContinuationOptions continuationOptions) @@ -2045,44 +2045,44 @@ public Task ContinueWhenAll(Task[] tasks, Func - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The type of the result that is returned by the /// delegate and associated with the created . + /// cref="Task{TResult}"/>. /// The array of tasks from which to continue. /// The function delegate to execute when all tasks in the /// array have completed. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The TaskScheduler + /// the created continuation Task. + /// The TaskScheduler /// that is used to schedule the created continuation . - /// The new continuation . - /// The exception that is thrown when the + /// cref="Task{TResult}"/>. + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAll. /// public Task ContinueWhenAll(Task[] tasks, Func continuationFunction, CancellationToken cancellationToken, @@ -2095,57 +2095,57 @@ public Task ContinueWhenAll(Task[] tasks, Func - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The type of the result of the antecedent . /// The type of the result that is returned by the /// delegate and associated with the created . + /// cref="Task{TResult}"/>. /// The array of tasks from which to continue. /// The function delegate to execute when all tasks in the /// array have completed. - /// The new continuation . - /// The exception that is thrown when the + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. public Task ContinueWhenAll(Task[] tasks, Func[], TResult> continuationFunction) { ArgumentNullException.ThrowIfNull(continuationFunction); - return TaskFactory.ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler); + return TaskFactory.ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler); } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The type of the result of the antecedent . /// The type of the result that is returned by the /// delegate and associated with the created . + /// cref="Task{TResult}"/>. /// The array of tasks from which to continue. /// The function delegate to execute when all tasks in the /// array have completed. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The new continuation . - /// The exception that is thrown when the + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task ContinueWhenAll(Task[] tasks, Func[], TResult> continuationFunction, @@ -2153,39 +2153,39 @@ public Task ContinueWhenAll(Task.ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler); + return TaskFactory.ContinueWhenAllImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler); } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The type of the result of the antecedent . /// The type of the result that is returned by the /// delegate and associated with the created . + /// cref="Task{TResult}"/>. /// The array of tasks from which to continue. /// The function delegate to execute when all tasks in the /// array have completed. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The new continuation . - /// The exception that is thrown when the + /// the created continuation Task. + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAll. /// public Task ContinueWhenAll(Task[] tasks, Func[], TResult> continuationFunction, @@ -2193,49 +2193,49 @@ public Task ContinueWhenAll(Task.ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler); + return TaskFactory.ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler); } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of a set of provided Tasks. /// /// The type of the result of the antecedent . /// The type of the result that is returned by the /// delegate and associated with the created . + /// cref="Task{TResult}"/>. /// The array of tasks from which to continue. /// The function delegate to execute when all tasks in the /// array have completed. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The TaskScheduler + /// the created continuation Task. + /// The TaskScheduler /// that is used to schedule the created continuation . - /// The new continuation . - /// The exception that is thrown when the + /// cref="Task{TResult}"/>. + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAll. /// public Task ContinueWhenAll(Task[] tasks, Func[], TResult> continuationFunction, @@ -2243,7 +2243,7 @@ public Task ContinueWhenAll(Task.ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler); + return TaskFactory.ContinueWhenAllImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler); } // @@ -2283,7 +2283,7 @@ public CompleteOnInvokePromise(IList tasks, bool isSyncBlocking) if (TplEventSource.Log.IsEnabled()) TplEventSource.Log.TraceOperationBegin(this.Id, "TaskFactory.ContinueWhenAny", 0); - if (Task.s_asyncDebuggingEnabled) + if (s_asyncDebuggingEnabled) AddToActiveTasks(this); } @@ -2302,7 +2302,7 @@ public void Invoke(Task completingTask) TplEventSource.Log.TraceOperationEnd(this.Id, AsyncCausalityStatus.Completed); } - if (Task.s_asyncDebuggingEnabled) + if (s_asyncDebuggingEnabled) RemoveFromActiveTasks(this); bool success = TrySetResult(completingTask); @@ -2399,20 +2399,20 @@ internal static void CommonCWAnyLogicCleanup(Task continuation) } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The array of tasks from which to continue when one task completes. /// The action delegate to execute when one task in the array completes. - /// The new continuation Task. - /// The exception that is thrown when the + /// The new continuation Task. + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. public Task ContinueWhenAny(Task[] tasks, Action continuationAction) { @@ -2422,24 +2422,24 @@ public Task ContinueWhenAny(Task[] tasks, Action continuationAction) } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The array of tasks from which to continue when one task completes. /// The action delegate to execute when one task in the array completes. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The new continuation Task. - /// The exception that is thrown when the + /// The new continuation Task. + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task ContinueWhenAny(Task[] tasks, Action continuationAction, CancellationToken cancellationToken) @@ -2450,30 +2450,30 @@ public Task ContinueWhenAny(Task[] tasks, Action continuationAction, Cance } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The array of tasks from which to continue when one task completes. /// The action delegate to execute when one task in the array completes. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The new continuation Task. - /// The exception that is thrown when the + /// the created continuation Task. + /// The new continuation Task. + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAny. /// public Task ContinueWhenAny(Task[] tasks, Action continuationAction, TaskContinuationOptions continuationOptions) @@ -2484,40 +2484,40 @@ public Task ContinueWhenAny(Task[] tasks, Action continuationAction, TaskC } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The array of tasks from which to continue when one task completes. /// The action delegate to execute when one task in the array completes. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The TaskScheduler + /// the created continuation Task. + /// The TaskScheduler /// that is used to schedule the created continuation Task. - /// The new continuation Task. - /// The exception that is thrown when the + /// cref="Task">Task. + /// The new continuation Task. + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAny. /// public Task ContinueWhenAny(Task[] tasks, Action continuationAction, CancellationToken cancellationToken, @@ -2530,24 +2530,24 @@ public Task ContinueWhenAny(Task[] tasks, Action continuationAction, Cance /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The type of the result that is returned by the /// delegate and associated with the created . + /// cref="Task{TResult}"/>. /// The array of tasks from which to continue when one task completes. /// The function delegate to execute when one task in the /// array completes. - /// The new continuation . - /// The exception that is thrown when the + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. public Task ContinueWhenAny(Task[] tasks, Func continuationFunction) { @@ -2557,28 +2557,28 @@ public Task ContinueWhenAny(Task[] tasks, Func } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The type of the result that is returned by the /// delegate and associated with the created . + /// cref="Task{TResult}"/>. /// The array of tasks from which to continue when one task completes. /// The function delegate to execute when one task in the /// array completes. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The new continuation . - /// The exception that is thrown when the + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task ContinueWhenAny(Task[] tasks, Func continuationFunction, CancellationToken cancellationToken) @@ -2589,34 +2589,34 @@ public Task ContinueWhenAny(Task[] tasks, Func } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The type of the result that is returned by the /// delegate and associated with the created . + /// cref="Task{TResult}"/>. /// The array of tasks from which to continue when one task completes. /// The function delegate to execute when one task in the /// array completes. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The new continuation . - /// The exception that is thrown when the + /// the created continuation Task. + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAny. /// public Task ContinueWhenAny(Task[] tasks, Func continuationFunction, TaskContinuationOptions continuationOptions) @@ -2627,44 +2627,44 @@ public Task ContinueWhenAny(Task[] tasks, Func } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The type of the result that is returned by the /// delegate and associated with the created . + /// cref="Task{TResult}"/>. /// The array of tasks from which to continue when one task completes. /// The function delegate to execute when one task in the /// array completes. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The TaskScheduler + /// the created continuation Task. + /// The TaskScheduler /// that is used to schedule the created continuation . - /// The new continuation . - /// The exception that is thrown when the + /// cref="Task{TResult}"/>. + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAny. /// public Task ContinueWhenAny(Task[] tasks, Func continuationFunction, CancellationToken cancellationToken, @@ -2676,57 +2676,57 @@ public Task ContinueWhenAny(Task[] tasks, Func } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The type of the result of the antecedent . /// The type of the result that is returned by the /// delegate and associated with the created . + /// cref="Task{TResult}"/>. /// The array of tasks from which to continue when one task completes. /// The function delegate to execute when one task in the /// array completes. - /// The new continuation . - /// The exception that is thrown when the + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. public Task ContinueWhenAny(Task[] tasks, Func, TResult> continuationFunction) { ArgumentNullException.ThrowIfNull(continuationFunction); - return TaskFactory.ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler); + return TaskFactory.ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler); } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The type of the result of the antecedent . /// The type of the result that is returned by the /// delegate and associated with the created . + /// cref="Task{TResult}"/>. /// The array of tasks from which to continue when one task completes. /// The function delegate to execute when one task in the /// array completes. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The new continuation . - /// The exception that is thrown when the + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task ContinueWhenAny(Task[] tasks, Func, TResult> continuationFunction, @@ -2734,39 +2734,39 @@ public Task ContinueWhenAny(Task.ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler); + return TaskFactory.ContinueWhenAnyImpl(tasks, continuationFunction, null, m_defaultContinuationOptions, cancellationToken, DefaultScheduler); } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The type of the result of the antecedent . /// The type of the result that is returned by the /// delegate and associated with the created . + /// cref="Task{TResult}"/>. /// The array of tasks from which to continue when one task completes. /// The function delegate to execute when one task in the /// array completes. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The new continuation . - /// The exception that is thrown when the + /// the created continuation Task. + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAny. /// public Task ContinueWhenAny(Task[] tasks, Func, TResult> continuationFunction, @@ -2774,49 +2774,49 @@ public Task ContinueWhenAny(Task.ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler); + return TaskFactory.ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, m_defaultCancellationToken, DefaultScheduler); } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The type of the result of the antecedent . /// The type of the result that is returned by the /// delegate and associated with the created . + /// cref="Task{TResult}"/>. /// The array of tasks from which to continue when one task completes. /// The function delegate to execute when one task in the /// array completes. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The TaskScheduler + /// the created continuation Task. + /// The TaskScheduler /// that is used to schedule the created continuation . - /// The new continuation . - /// The exception that is thrown when the + /// cref="Task{TResult}"/>. + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAny. /// public Task ContinueWhenAny(Task[] tasks, Func, TResult> continuationFunction, @@ -2824,54 +2824,54 @@ public Task ContinueWhenAny(Task.ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler); + return TaskFactory.ContinueWhenAnyImpl(tasks, continuationFunction, null, continuationOptions, cancellationToken, scheduler); } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The type of the result of the antecedent . /// The array of tasks from which to continue when one task completes. /// The action delegate to execute when one task in the /// array completes. - /// The new continuation . - /// The exception that is thrown when the + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. public Task ContinueWhenAny(Task[] tasks, Action> continuationAction) { ArgumentNullException.ThrowIfNull(continuationAction); - return TaskFactory.ContinueWhenAnyImpl(tasks, null, continuationAction, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler); + return TaskFactory.ContinueWhenAnyImpl(tasks, null, continuationAction, m_defaultContinuationOptions, m_defaultCancellationToken, DefaultScheduler); } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The type of the result of the antecedent . /// The array of tasks from which to continue when one task completes. /// The action delegate to execute when one task in the /// array completes. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The new continuation . - /// The exception that is thrown when the + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// public Task ContinueWhenAny(Task[] tasks, Action> continuationAction, @@ -2879,35 +2879,35 @@ public Task ContinueWhenAny(Task[] tasks, { ArgumentNullException.ThrowIfNull(continuationAction); - return TaskFactory.ContinueWhenAnyImpl(tasks, null, continuationAction, m_defaultContinuationOptions, cancellationToken, DefaultScheduler); + return TaskFactory.ContinueWhenAnyImpl(tasks, null, continuationAction, m_defaultContinuationOptions, cancellationToken, DefaultScheduler); } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The type of the result of the antecedent . /// The array of tasks from which to continue when one task completes. /// The action delegate to execute when one task in the /// array completes. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The new continuation . - /// The exception that is thrown when the + /// the created continuation Task. + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAny. /// public Task ContinueWhenAny(Task[] tasks, Action> continuationAction, @@ -2915,45 +2915,45 @@ public Task ContinueWhenAny(Task[] tasks, { ArgumentNullException.ThrowIfNull(continuationAction); - return TaskFactory.ContinueWhenAnyImpl(tasks, null, continuationAction, continuationOptions, m_defaultCancellationToken, DefaultScheduler); + return TaskFactory.ContinueWhenAnyImpl(tasks, null, continuationAction, continuationOptions, m_defaultCancellationToken, DefaultScheduler); } /// - /// Creates a continuation Task + /// Creates a continuation Task /// that will be started upon the completion of any Task in the provided set. /// /// The type of the result of the antecedent . /// The array of tasks from which to continue when one task completes. /// The action delegate to execute when one task in the /// array completes. - /// The CancellationToken + /// The CancellationToken /// that will be assigned to the new continuation task. - /// The + /// The /// TaskContinuationOptions value that controls the behavior of - /// the created continuation Task. - /// The TaskScheduler + /// the created continuation Task. + /// The TaskScheduler /// that is used to schedule the created continuation . - /// The new continuation . - /// The exception that is thrown when the + /// cref="Task{TResult}"/>. + /// The new continuation . + /// The exception that is thrown when the /// array is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument is null. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array contains a null value. - /// The exception that is thrown when the + /// The exception that is thrown when the /// array is empty. - /// The exception that is thrown when the + /// The exception that is thrown when the /// argument specifies an invalid TaskContinuationOptions /// value. - /// The provided CancellationToken + /// The provided CancellationToken /// has already been disposed. /// /// - /// The NotOn* and OnlyOn* TaskContinuationOptions, - /// which constrain for which TaskStatus states a continuation + /// The NotOn* and OnlyOn* TaskContinuationOptions, + /// which constrain for which TaskStatus states a continuation /// will be executed, are illegal with ContinueWhenAny. /// public Task ContinueWhenAny(Task[] tasks, Action> continuationAction, @@ -2961,7 +2961,7 @@ public Task ContinueWhenAny(Task[] tasks, { ArgumentNullException.ThrowIfNull(continuationAction); - return TaskFactory.ContinueWhenAnyImpl(tasks, null, continuationAction, continuationOptions, cancellationToken, scheduler); + return TaskFactory.ContinueWhenAnyImpl(tasks, null, continuationAction, continuationOptions, cancellationToken, scheduler); } // Check task array and return a defensive copy. diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskScheduler.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskScheduler.cs index 222afab971556b..5d31ac050810e0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskScheduler.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskScheduler.cs @@ -20,7 +20,7 @@ namespace System.Threading.Tasks /// /// /// - /// TaskScheduler acts as the extension point for all + /// TaskScheduler acts as the extension point for all /// pluggable scheduling logic. This includes mechanisms such as how to schedule a task for execution, and /// how scheduled tasks should be exposed to debuggers. /// @@ -39,11 +39,11 @@ public abstract class TaskScheduler // /// - /// Queues a Task to the scheduler. + /// Queues a Task to the scheduler. /// /// /// - /// A class derived from TaskScheduler + /// A class derived from TaskScheduler /// implements this method to accept tasks being scheduled on the scheduler. /// A typical implementation would store the task in an internal data structure, which would /// be serviced by threads that would execute those tasks at some time in the future. @@ -54,12 +54,12 @@ public abstract class TaskScheduler /// for maintaining the consistency of the system. /// /// - /// The Task to be queued. - /// The argument is null. + /// The Task to be queued. + /// The argument is null. protected internal abstract void QueueTask(Task task); /// - /// Determines whether the provided Task + /// Determines whether the provided Task /// can be executed synchronously in this call, and if it can, executes it. /// /// @@ -87,21 +87,21 @@ public abstract class TaskScheduler /// executing the given task as far as its own scheduling and execution policies are concerned. /// /// - /// The Task to be + /// The Task to be /// executed. /// A Boolean denoting whether or not task has previously been /// queued. If this parameter is True, then the task may have been previously queued (scheduled); if /// False, then the task is known not to have been queued, and this call is being made in order to /// execute the task inline without queueing it. /// A Boolean value indicating whether the task was executed inline. - /// The argument is + /// The argument is /// null. - /// The was already + /// The was already /// executed. protected abstract bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQueued); /// - /// Generates an enumerable of Task instances + /// Generates an enumerable of Task instances /// currently queued to the scheduler waiting to be executed. /// /// @@ -116,7 +116,7 @@ public abstract class TaskScheduler /// It is important to note that, when this method is called, all other threads in the process will /// be frozen. Therefore, it's important to avoid synchronization with other threads that may lead to /// blocking. If synchronization is necessary, the method should prefer to throw a + /// cref="NotSupportedException"/> /// than to block, which could cause a debugger to experience delays. Additionally, this method and /// the enumerable returned must not modify any globally visible state. /// @@ -138,7 +138,7 @@ public abstract class TaskScheduler /// /// An enumerable that allows traversal of tasks currently queued to this scheduler. /// - /// + /// /// This scheduler is unable to generate a list of queued tasks at this time. /// protected abstract IEnumerable? GetScheduledTasks(); @@ -200,12 +200,12 @@ internal bool TryRunInline(Task task, bool taskWasPreviouslyQueued) } /// - /// Attempts to dequeue a Task that was previously queued to + /// Attempts to dequeue a Task that was previously queued to /// this scheduler. /// - /// The Task to be dequeued. + /// The Task to be dequeued. /// A Boolean denoting whether the argument was successfully dequeued. - /// The argument is null. + /// The argument is null. protected internal virtual bool TryDequeue(Task task) { return false; @@ -263,7 +263,7 @@ internal void InternalQueueTask(Task task) // /// - /// Initializes the . + /// Initializes the . /// protected TaskScheduler() { @@ -292,12 +292,12 @@ private void AddToActiveTaskSchedulers() } /// - /// Gets the default TaskScheduler instance. + /// Gets the default TaskScheduler instance. /// public static TaskScheduler Default => s_defaultTaskScheduler; /// - /// Gets the TaskScheduler + /// Gets the TaskScheduler /// associated with the currently executing task. /// /// @@ -306,7 +306,7 @@ private void AddToActiveTaskSchedulers() public static TaskScheduler Current => InternalCurrent ?? Default; /// - /// Gets the TaskScheduler + /// Gets the TaskScheduler /// associated with the currently executing task. /// /// @@ -325,20 +325,20 @@ internal static TaskScheduler? InternalCurrent /// /// Creates a - /// associated with the current . + /// associated with the current . /// /// - /// All Task instances queued to + /// All Task instances queued to /// the returned scheduler will be executed through a call to the - /// Post method + /// Post method /// on that context. /// /// /// A associated with - /// the current SynchronizationContext, as - /// determined by SynchronizationContext.Current. + /// the current SynchronizationContext, as + /// determined by SynchronizationContext.Current. /// - /// + /// /// The current SynchronizationContext may not be used as a TaskScheduler. /// public static TaskScheduler FromCurrentSynchronizationContext() @@ -375,12 +375,12 @@ public int Id } /// - /// Attempts to execute the provided Task + /// Attempts to execute the provided Task /// on this scheduler. /// /// /// - /// Scheduler implementations are provided with Task + /// Scheduler implementations are provided with Task /// instances to be executed through either the method or the /// method. When the scheduler deems it appropriate to run the /// provided task, should be used to do so. TryExecuteTask handles all @@ -394,8 +394,8 @@ public int Id /// /// /// - /// A Task object to be executed. - /// + /// A Task object to be executed. + /// /// The is not associated with this scheduler. /// /// A Boolean that is true if was successfully executed, false if it @@ -417,13 +417,13 @@ protected bool TryExecuteTask(Task task) // /// - /// Occurs when a faulted 's unobserved exception is about to trigger exception escalation + /// Occurs when a faulted 's unobserved exception is about to trigger exception escalation /// policy, which, by default, would terminate the process. /// /// /// This AppDomain-wide event provides a mechanism to prevent exception /// escalation policy (which, by default, terminates the process) from triggering. - /// Each handler is passed a + /// Each handler is passed a /// instance, which may be used to examine the exception and to mark it as observed. /// public static event EventHandler? UnobservedTaskException; @@ -440,7 +440,7 @@ internal static void PublishUnobservedTaskException(object sender, UnobservedTas } /// - /// Provides an array of all queued Task instances + /// Provides an array of all queued Task instances /// for the debugger. /// /// @@ -448,8 +448,8 @@ internal static void PublishUnobservedTaskException(object sender, UnobservedTas /// Note that this function is only meant to be invoked by a debugger remotely. /// It should not be called by any other codepaths. /// - /// An array of Task instances. - /// + /// An array of Task instances. + /// /// This scheduler is unable to generate a list of queued tasks at this time. /// internal Task[]? GetScheduledTasksForDebugger() @@ -477,14 +477,14 @@ internal static void PublishUnobservedTaskException(object sender, UnobservedTas } /// - /// Provides an array of all active TaskScheduler + /// Provides an array of all active TaskScheduler /// instances for the debugger. /// /// /// This function is only meant to be invoked by a debugger remotely. /// It should not be called by any other codepaths. /// - /// An array of TaskScheduler instances. + /// An array of TaskScheduler instances. internal static TaskScheduler[] GetTaskSchedulersForDebugger() { if (s_activeTaskSchedulers == null) @@ -532,46 +532,21 @@ public SystemThreadingTasks_TaskSchedulerDebugView(TaskScheduler scheduler) // returns the scheduler's GetScheduledTasks public IEnumerable? ScheduledTasks => m_taskScheduler.GetScheduledTasks(); } - - // TODO https://github.com/dotnet/runtime/issues/20025: Consider exposing publicly. - /// Gets an awaiter used to queue a continuation to this TaskScheduler. - internal TaskSchedulerAwaiter GetAwaiter() => new TaskSchedulerAwaiter(this); - - /// Awaiter used to queue a continuation to a specified task scheduler. - internal readonly struct TaskSchedulerAwaiter : ICriticalNotifyCompletion - { - private readonly TaskScheduler _scheduler; - public TaskSchedulerAwaiter(TaskScheduler scheduler) => _scheduler = scheduler; - public bool IsCompleted => false; - public void GetResult() { } - public void OnCompleted(Action continuation) => Task.Factory.StartNew(continuation, CancellationToken.None, TaskCreationOptions.DenyChildAttach, _scheduler); - public void UnsafeOnCompleted(Action continuation) - { - if (ReferenceEquals(_scheduler, Default)) - { - ThreadPool.UnsafeQueueUserWorkItem(s => s(), continuation, preferLocal: true); - } - else - { - OnCompleted(continuation); - } - } - } } /// /// A TaskScheduler implementation that executes all tasks queued to it through a call to - /// on the - /// that its associated with. The default constructor for this class binds to the current + /// on the + /// that its associated with. The default constructor for this class binds to the current /// internal sealed class SynchronizationContextTaskScheduler : TaskScheduler { private readonly SynchronizationContext m_synchronizationContext; /// - /// Constructs a SynchronizationContextTaskScheduler associated with + /// Constructs a SynchronizationContextTaskScheduler associated with /// - /// This constructor expects to be set. + /// This constructor expects to be set. internal SynchronizationContextTaskScheduler() { m_synchronizationContext = SynchronizationContext.Current ?? @@ -580,9 +555,9 @@ internal SynchronizationContextTaskScheduler() } /// - /// Implementation of for this scheduler class. + /// Implementation of for this scheduler class. /// - /// Simply posts the tasks to be executed on the associated . + /// Simply posts the tasks to be executed on the associated . /// /// protected internal override void QueueTask(Task task) @@ -591,10 +566,10 @@ protected internal override void QueueTask(Task task) } /// - /// Implementation of for this scheduler class. + /// Implementation of for this scheduler class. /// /// The task will be executed inline only if the call happens within - /// the associated . + /// the associated . /// /// /// @@ -616,10 +591,10 @@ protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQu } /// - /// Implements the property for + /// Implements the property for /// this scheduler class. /// - /// By default it returns 1, because a based + /// By default it returns 1, because a based /// scheduler only supports execution on a single thread. /// public override int MaximumConcurrencyLevel => 1; @@ -633,7 +608,7 @@ protected override bool TryExecuteTaskInline(Task task, bool taskWasPreviouslyQu } /// - /// Provides data for the event that is raised when a faulted 's + /// Provides data for the event that is raised when a faulted 's /// exception goes unobserved. /// /// diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskSchedulerException.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskSchedulerException.cs index 5e3ebd6f9f36ed..d935bbcc696461 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskSchedulerException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskSchedulerException.cs @@ -10,27 +10,28 @@ // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Threading.Tasks { /// /// Represents an exception used to communicate an invalid operation by a - /// . + /// . /// [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class TaskSchedulerException : Exception { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public TaskSchedulerException() : base(SR.TaskSchedulerException_ctor_DefaultMessage) // { } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class with a specified error message. /// /// The error message that explains the reason for the exception. @@ -39,7 +40,7 @@ public TaskSchedulerException(string? message) : base(message) } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class using the default error message and a reference to the inner exception that is the cause of /// this exception. /// @@ -50,7 +51,7 @@ public TaskSchedulerException(Exception? innerException) } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class with a specified error message and a reference to the inner exception that is the cause of /// this exception. /// @@ -61,12 +62,12 @@ public TaskSchedulerException(string? message, Exception? innerException) : base } /// - /// Initializes a new instance of the + /// Initializes a new instance of the /// class with serialized data. /// - /// The that holds + /// The that holds /// the serialized object data about the exception being thrown. - /// The that + /// The that /// contains contextual information about the source or destination. [Obsolete(Obsoletions.LegacyFormatterImplMessage, DiagnosticId = Obsoletions.LegacyFormatterImplDiagId, UrlFormat = Obsoletions.SharedUrlFormat)] [EditorBrowsable(EditorBrowsableState.Never)] diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ThreadPoolTaskScheduler.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ThreadPoolTaskScheduler.cs index e1469c5cc8b80b..45339d9bdd892b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ThreadPoolTaskScheduler.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/ThreadPoolTaskScheduler.cs @@ -25,7 +25,7 @@ internal sealed class ThreadPoolTaskScheduler : TaskScheduler /// internal ThreadPoolTaskScheduler() { - _ = base.Id; // force ID creation of the default scheduler + _ = Id; // force ID creation of the default scheduler } // static delegate for threads allocated to handle LongRunning tasks. diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TplEventSource.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TplEventSource.cs index f8b73388328019..deb8e283da6896 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TplEventSource.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TplEventSource.cs @@ -303,7 +303,7 @@ public void TaskCompleted( /// [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern", Justification = EventSourceSuppressMessage)] - [Event(TASKWAITBEGIN_ID, Version = 3, Task = TplEventSource.Tasks.TaskWait, Opcode = EventOpcode.Send, + [Event(TASKWAITBEGIN_ID, Version = 3, Task = Tasks.TaskWait, Opcode = EventOpcode.Send, Level = EventLevel.Informational, Keywords = Keywords.TaskTransfer | Keywords.Tasks, Message = "Beginning wait ({3}) on Task {2}.")] public void TaskWaitBegin( @@ -545,7 +545,7 @@ public void NewID(int TaskID) [NonEvent] public void IncompleteAsyncMethod(IAsyncStateMachineBox stateMachineBox) { - System.Diagnostics.Debug.Assert(stateMachineBox != null); + Diagnostics.Debug.Assert(stateMachineBox != null); if (IsEnabled() && IsEnabled(EventLevel.Warning, Keywords.AsyncMethod)) { IAsyncStateMachine stateMachine = stateMachineBox.GetStateMachineObject(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.cs index d80024f7b8076a..5cc867a9e02c86 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Thread.cs @@ -176,7 +176,7 @@ internal static void ThrowIfNoThreadStart(bool internalThread = false) /// There is not enough memory available to start this thread. /// This thread was created using a delegate instead of a delegate. #if !FEATURE_WASM_THREADS - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [UnsupportedOSPlatform("browser")] #endif public void Start(object? parameter) => Start(parameter, captureContext: true); @@ -190,7 +190,7 @@ internal static void ThrowIfNoThreadStart(bool internalThread = false) /// explicitly avoids capturing the current context and flowing it to the invocation. /// #if !FEATURE_WASM_THREADS - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [UnsupportedOSPlatform("browser")] #endif public void UnsafeStart(object? parameter) => Start(parameter, captureContext: false); @@ -221,7 +221,7 @@ private void Start(object? parameter, bool captureContext, bool internalThread = /// The thread has already been started. /// There is not enough memory available to start this thread. #if !FEATURE_WASM_THREADS - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [UnsupportedOSPlatform("browser")] #endif public void Start() => Start(captureContext: true); @@ -233,7 +233,7 @@ private void Start(object? parameter, bool captureContext, bool internalThread = /// explicitly avoids capturing the current context and flowing it to the invocation. /// #if !FEATURE_WASM_THREADS - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [UnsupportedOSPlatform("browser")] #endif public void UnsafeStart() => Start(captureContext: false); diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadAbortException.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadAbortException.cs index f1cc648fc4a9d4..b20c3e90b19a68 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadAbortException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadAbortException.cs @@ -13,12 +13,13 @@ ** =============================================================================*/ +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Threading { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class ThreadAbortException : SystemException { internal ThreadAbortException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadInterruptedException.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadInterruptedException.cs index b6d9d7fcd8422d..193747c944c343 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadInterruptedException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadInterruptedException.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Threading @@ -10,7 +11,7 @@ namespace System.Threading /// An exception class to indicate that the thread was interrupted from a waiting state. /// [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class ThreadInterruptedException : SystemException { public ThreadInterruptedException() : base( 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 1f54950f7d1504..fd8584b22c0ebb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadLocal.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadLocal.cs @@ -61,7 +61,7 @@ public class ThreadLocal : IDisposable private bool _trackAllValues; /// - /// Initializes the instance. + /// Initializes the instance. /// public ThreadLocal() { @@ -69,7 +69,7 @@ public ThreadLocal() } /// - /// Initializes the instance. + /// Initializes the instance. /// /// Whether to track all values set on the instance and expose them through the Values property. public ThreadLocal(bool trackAllValues) @@ -79,14 +79,14 @@ public ThreadLocal(bool trackAllValues) /// - /// Initializes the instance with the + /// Initializes the instance with the /// specified function. /// /// - /// The invoked to produce a lazily-initialized value when + /// The invoked to produce a lazily-initialized value when /// an attempt is made to retrieve without it having been previously initialized. /// - /// + /// /// is a null reference (Nothing in Visual Basic). /// public ThreadLocal(Func valueFactory) @@ -97,15 +97,15 @@ public ThreadLocal(Func valueFactory) } /// - /// Initializes the instance with the + /// Initializes the instance with the /// specified function. /// /// - /// The invoked to produce a lazily-initialized value when + /// The invoked to produce a lazily-initialized value when /// an attempt is made to retrieve without it having been previously initialized. /// /// Whether to track all values set on the instance and expose them via the Values property. - /// + /// /// is a null reference (Nothing in Visual Basic). /// public ThreadLocal(Func valueFactory, bool trackAllValues) @@ -129,7 +129,7 @@ private void Initialize(Func? valueFactory, bool trackAllValues) } /// - /// Releases the resources used by this instance. + /// Releases the resources used by this instance. /// ~ThreadLocal() { @@ -140,10 +140,10 @@ private void Initialize(Func? valueFactory, bool trackAllValues) #region IDisposable Members /// - /// Releases the resources used by this instance. + /// Releases the resources used by this instance. /// /// - /// Unlike most of the members of , this method is not thread-safe. + /// Unlike most of the members of , this method is not thread-safe. /// public void Dispose() { @@ -152,13 +152,13 @@ public void Dispose() } /// - /// Releases the resources used by this instance. + /// Releases the resources used by this instance. /// /// /// A Boolean value that indicates whether this method is being called due to a call to . /// /// - /// Unlike most of the members of , this method is not thread-safe. + /// Unlike most of the members of , this method is not thread-safe. /// protected virtual void Dispose(bool disposing) { @@ -206,13 +206,13 @@ protected virtual void Dispose(bool disposing) /// Creates and returns a string representation of this instance for the current thread. /// The result of calling on the . - /// + /// /// The for the current thread is a null reference (Nothing in Visual Basic). /// - /// + /// /// The initialization function referenced in an improper manner. /// - /// + /// /// The instance has been disposed. /// /// @@ -227,10 +227,10 @@ protected virtual void Dispose(bool disposing) /// /// Gets or sets the value of this instance for the current thread. /// - /// + /// /// The initialization function referenced in an improper manner. /// - /// + /// /// The instance has been disposed. /// /// @@ -414,7 +414,7 @@ private void CreateLinkedSlot(LinkedSlotVolatile[] slotArray, int id, T value) /// /// Gets a list for all of the values currently stored by all of the threads that have accessed this instance. /// - /// + /// /// The instance has been disposed. /// public IList Values @@ -471,7 +471,7 @@ private int ValuesCountForDebugDisplay /// /// Gets whether is initialized on the current thread. /// - /// + /// /// The instance has been disposed. /// public bool IsValueCreated diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolBoundHandleOverlapped.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolBoundHandleOverlapped.cs index 46a72e7222ea91..4034efe58d5b1e 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolBoundHandleOverlapped.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolBoundHandleOverlapped.cs @@ -33,7 +33,7 @@ public ThreadPoolBoundHandleOverlapped(IOCompletionCallback callback, object? st private static void CompletionCallback(uint errorCode, uint numBytes, NativeOverlapped* nativeOverlapped) { - ThreadPoolBoundHandleOverlapped overlapped = (ThreadPoolBoundHandleOverlapped)Overlapped.Unpack(nativeOverlapped); + ThreadPoolBoundHandleOverlapped overlapped = (ThreadPoolBoundHandleOverlapped)Unpack(nativeOverlapped); // // The Win32 thread pool implementation of ThreadPoolBoundHandle does not permit reuse of NativeOverlapped 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 420d26d917a21a..597cd4b46f2b4d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadPoolWorkQueue.cs @@ -1375,7 +1375,7 @@ public static partial class ThreadPool internal static bool EnableWorkerTracking => IsWorkerTrackingEnabledInConfig && EventSource.IsSupported; #if !FEATURE_WASM_THREADS - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [UnsupportedOSPlatform("browser")] #endif [CLSCompliant(false)] public static RegisteredWaitHandle RegisterWaitForSingleObject( @@ -1392,7 +1392,7 @@ public static RegisteredWaitHandle RegisterWaitForSingleObject( } #if !FEATURE_WASM_THREADS - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [UnsupportedOSPlatform("browser")] #endif [CLSCompliant(false)] public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject( @@ -1409,7 +1409,7 @@ public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject( } #if !FEATURE_WASM_THREADS - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [UnsupportedOSPlatform("browser")] #endif public static RegisteredWaitHandle RegisterWaitForSingleObject( WaitHandle waitObject, @@ -1424,7 +1424,7 @@ public static RegisteredWaitHandle RegisterWaitForSingleObject( } #if !FEATURE_WASM_THREADS - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [UnsupportedOSPlatform("browser")] #endif public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject( WaitHandle waitObject, @@ -1439,7 +1439,7 @@ public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject( } #if !FEATURE_WASM_THREADS - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [UnsupportedOSPlatform("browser")] #endif public static RegisteredWaitHandle RegisterWaitForSingleObject( WaitHandle waitObject, @@ -1455,7 +1455,7 @@ public static RegisteredWaitHandle RegisterWaitForSingleObject( } #if !FEATURE_WASM_THREADS - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [UnsupportedOSPlatform("browser")] #endif public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject( WaitHandle waitObject, @@ -1471,7 +1471,7 @@ public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject( } #if !FEATURE_WASM_THREADS - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [UnsupportedOSPlatform("browser")] #endif public static RegisteredWaitHandle RegisterWaitForSingleObject( WaitHandle waitObject, @@ -1490,7 +1490,7 @@ bool executeOnlyOnce } #if !FEATURE_WASM_THREADS - [System.Runtime.Versioning.UnsupportedOSPlatformAttribute("browser")] + [UnsupportedOSPlatform("browser")] #endif public static RegisteredWaitHandle UnsafeRegisterWaitForSingleObject( WaitHandle waitObject, diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadStartException.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadStartException.cs index 915495526101bf..cd852825bbe441 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadStartException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadStartException.cs @@ -1,12 +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.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Threading { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class ThreadStartException : SystemException { internal ThreadStartException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadStateException.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadStateException.cs index a4622f30eed777..20bd715c20145f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadStateException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/ThreadStateException.cs @@ -12,12 +12,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Threading { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class ThreadStateException : SystemException { public ThreadStateException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/Timeout.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/Timeout.cs index bbff950f2f331a..60490d89953f0f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/Timeout.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/Timeout.cs @@ -8,7 +8,7 @@ namespace System.Threading // public static class Timeout { - public static readonly TimeSpan InfiniteTimeSpan = new TimeSpan(0, 0, 0, 0, Timeout.Infinite); + public static readonly TimeSpan InfiniteTimeSpan = new TimeSpan(0, 0, 0, 0, Infinite); public const int Infinite = -1; internal const uint UnsignedInfinite = unchecked((uint)-1); diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/WaitHandleCannotBeOpenedException.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/WaitHandleCannotBeOpenedException.cs index 51e81d9ce2092e..2babfd6e213467 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/WaitHandleCannotBeOpenedException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/WaitHandleCannotBeOpenedException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System.Threading { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class WaitHandleCannotBeOpenedException : ApplicationException { public WaitHandleCannotBeOpenedException() : base(SR.Threading_WaitHandleCannotBeOpenedException) diff --git a/src/libraries/System.Private.CoreLib/src/System/Threading/WaitHandleExtensions.cs b/src/libraries/System.Private.CoreLib/src/System/Threading/WaitHandleExtensions.cs index 5fc146dd8a6ef2..e0227a95e32226 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Threading/WaitHandleExtensions.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Threading/WaitHandleExtensions.cs @@ -10,8 +10,8 @@ public static class WaitHandleExtensions /// /// Gets the native operating system handle. /// - /// The to operate on. - /// A representing the native operating system handle. + /// The to operate on. + /// A representing the native operating system handle. public static SafeWaitHandle GetSafeWaitHandle(this WaitHandle waitHandle) { ArgumentNullException.ThrowIfNull(waitHandle); @@ -22,8 +22,8 @@ public static SafeWaitHandle GetSafeWaitHandle(this WaitHandle waitHandle) /// /// Sets the native operating system handle /// - /// The to operate on. - /// A representing the native operating system handle. + /// The to operate on. + /// A representing the native operating system handle. public static void SetSafeWaitHandle(this WaitHandle waitHandle, SafeWaitHandle? value) { ArgumentNullException.ThrowIfNull(waitHandle); diff --git a/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs b/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs index 3f4ae02f9befc6..670b21e2159aff 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ThrowHelper.cs @@ -40,6 +40,8 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Numerics; +using System.Reflection; +using System.Runtime; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics; @@ -605,6 +607,22 @@ internal static void ThrowFormatIndexOutOfRange() throw new FormatException(SR.Format_IndexOutOfRange); } + internal static AmbiguousMatchException GetAmbiguousMatchException(MemberInfo memberInfo) + { + Type? declaringType = memberInfo.DeclaringType; + return new AmbiguousMatchException(SR.Format(SR.Arg_AmbiguousMatchException_MemberInfo, declaringType, memberInfo)); + } + + internal static AmbiguousMatchException GetAmbiguousMatchException(Attribute attribute) + { + return new AmbiguousMatchException(SR.Format(SR.Arg_AmbiguousMatchException_Attribute, attribute)); + } + + internal static AmbiguousMatchException GetAmbiguousMatchException(CustomAttributeData customAttributeData) + { + return new AmbiguousMatchException(SR.Format(SR.Arg_AmbiguousMatchException_CustomAttributeData, customAttributeData)); + } + private static Exception GetArraySegmentCtorValidationFailedException(Array? array, int offset, int count) { if (array == null) @@ -674,7 +692,7 @@ internal static void IfNullAndNullsAreIllegalThenThrow(object? value, Excepti { // Note that default(T) is not equal to null for value types except when T is Nullable. if (!(default(T) == null) && value == null) - ThrowHelper.ThrowArgumentNullException(argName); + ThrowArgumentNullException(argName); } // Throws if 'T' is disallowed in Vector in the Numerics namespace. diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeSpan.cs b/src/libraries/System.Private.CoreLib/src/System/TimeSpan.cs index acaf1fc2661cd6..ec448d9195a340 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeSpan.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeSpan.cs @@ -273,7 +273,7 @@ public static TimeSpan FromDays(double value) public TimeSpan Duration() { - if (Ticks == TimeSpan.MinValue.Ticks) + if (Ticks == MinValue.Ticks) throw new OverflowException(SR.Overflow_Duration); return new TimeSpan(_ticks >= 0 ? _ticks : -_ticks); } @@ -319,7 +319,7 @@ private static TimeSpan IntervalFromDoubleTicks(double ticks) if ((ticks > long.MaxValue) || (ticks < long.MinValue) || double.IsNaN(ticks)) ThrowHelper.ThrowOverflowException_TimeSpanTooLong(); if (ticks == long.MaxValue) - return TimeSpan.MaxValue; + return MaxValue; return new TimeSpan((long)ticks); } @@ -360,7 +360,7 @@ public static TimeSpan FromMinutes(double value) public TimeSpan Negate() { - if (Ticks == TimeSpan.MinValue.Ticks) + if (Ticks == MinValue.Ticks) throw new OverflowException(SR.Overflow_NegateTwosCompNum); return new TimeSpan(-_ticks); } @@ -572,7 +572,7 @@ public bool TryFormat(Span utf8Destination, out int bytesWritten, [StringS public static TimeSpan operator -(TimeSpan t) { - if (t._ticks == TimeSpan.MinValue._ticks) + if (t._ticks == MinValue._ticks) throw new OverflowException(SR.Overflow_NegateTwosCompNum); return new TimeSpan(-t._ticks); } diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZone.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZone.cs index 071bd0880551c3..4a572bd986f6fd 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZone.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZone.cs @@ -123,7 +123,7 @@ public virtual DateTime ToLocalTime(DateTime time) return time; } bool isAmbiguousLocalDst = false; - long offset = ((CurrentSystemTimeZone)(TimeZone.CurrentTimeZone)).GetUtcOffsetFromUniversalTime(time, ref isAmbiguousLocalDst); + long offset = ((CurrentSystemTimeZone)(CurrentTimeZone)).GetUtcOffsetFromUniversalTime(time, ref isAmbiguousLocalDst); return new DateTime(time.Ticks + offset, DateTimeKind.Local, isAmbiguousLocalDst); } diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.AdjustmentRule.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.AdjustmentRule.cs index 12dbeb4fdb1bb5..327ec26f8b1e6d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.AdjustmentRule.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.AdjustmentRule.cs @@ -240,7 +240,7 @@ private static void AdjustDaylightDeltaToExpectedRange(ref TimeSpan daylightDelt baseUtcOffsetDelta -= DaylightDeltaAdjustment; } - System.Diagnostics.Debug.Assert(daylightDelta <= MaxDaylightDelta && daylightDelta >= -MaxDaylightDelta, + Diagnostics.Debug.Assert(daylightDelta <= MaxDaylightDelta && daylightDelta >= -MaxDaylightDelta, "DaylightDelta should not ever be more than 24h"); } diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs index 0cd7cb3ebf3437..2d354edaa1620d 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneInfo.cs @@ -6,6 +6,7 @@ using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Globalization; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; using System.Threading; @@ -28,7 +29,7 @@ internal enum TimeZoneInfoOptions } [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed partial class TimeZoneInfo : IEquatable, ISerializable, IDeserializationCallback { private enum TimeZoneInfoResult @@ -892,7 +893,7 @@ public static TimeZoneInfo CreateCustomTimeZone( string? displayName, string? standardDisplayName) { - bool hasIanaId = TimeZoneInfo.TryConvertIanaIdToWindowsId(id, allocate: false, out _); + bool hasIanaId = TryConvertIanaIdToWindowsId(id, allocate: false, out _); return new TimeZoneInfo( id, @@ -943,7 +944,7 @@ public static TimeZoneInfo CreateCustomTimeZone( adjustmentRules = (AdjustmentRule[])adjustmentRules.Clone(); } - bool hasIanaId = TimeZoneInfo.TryConvertIanaIdToWindowsId(id, allocate: false, out _); + bool hasIanaId = TryConvertIanaIdToWindowsId(id, allocate: false, out _); return new TimeZoneInfo( id, diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeZoneNotFoundException.cs b/src/libraries/System.Private.CoreLib/src/System/TimeZoneNotFoundException.cs index ee12022332dcff..507f22c5a95d28 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeZoneNotFoundException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeZoneNotFoundException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class TimeZoneNotFoundException : Exception { public TimeZoneNotFoundException() diff --git a/src/libraries/System.Private.CoreLib/src/System/TimeoutException.cs b/src/libraries/System.Private.CoreLib/src/System/TimeoutException.cs index 6531c86a8815f7..2ff38e5abbe532 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TimeoutException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TimeoutException.cs @@ -11,12 +11,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class TimeoutException : SystemException { public TimeoutException() diff --git a/src/libraries/System.Private.CoreLib/src/System/Tuple.cs b/src/libraries/System.Private.CoreLib/src/System/Tuple.cs index 3b8544db458737..38c1973bbd8006 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Tuple.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Tuple.cs @@ -101,7 +101,7 @@ internal static int CombineHashCodes(int h1, int h2, int h3, int h4, int h5, int } [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class Tuple : IStructuralEquatable, IStructuralComparable, IComparable, ITupleInternal, ITuple { private readonly T1 m_Item1; // Do not rename (binary serialization) @@ -218,7 +218,7 @@ private string ToString(StringBuilder sb) } [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class Tuple : IStructuralEquatable, IStructuralComparable, IComparable, ITupleInternal, ITuple { private readonly T1 m_Item1; // Do not rename (binary serialization) @@ -340,7 +340,7 @@ private string ToString(StringBuilder sb) } [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class Tuple : IStructuralEquatable, IStructuralComparable, IComparable, ITupleInternal, ITuple { private readonly T1 m_Item1; // Do not rename (binary serialization) @@ -472,7 +472,7 @@ private string ToString(StringBuilder sb) } [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class Tuple : IStructuralEquatable, IStructuralComparable, IComparable, ITupleInternal, ITuple { private readonly T1 m_Item1; // Do not rename (binary serialization) @@ -614,7 +614,7 @@ private string ToString(StringBuilder sb) } [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class Tuple : IStructuralEquatable, IStructuralComparable, IComparable, ITupleInternal, ITuple { private readonly T1 m_Item1; // Do not rename (binary serialization) @@ -766,7 +766,7 @@ private string ToString(StringBuilder sb) } [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class Tuple : IStructuralEquatable, IStructuralComparable, IComparable, ITupleInternal, ITuple { private readonly T1 m_Item1; // Do not rename (binary serialization) @@ -928,7 +928,7 @@ private string ToString(StringBuilder sb) } [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class Tuple : IStructuralEquatable, IStructuralComparable, IComparable, ITupleInternal, ITuple { private readonly T1 m_Item1; // Do not rename (binary serialization) @@ -1100,7 +1100,7 @@ private string ToString(StringBuilder sb) } [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class Tuple : IStructuralEquatable, IStructuralComparable, IComparable, ITupleInternal, ITuple where TRest : notnull { private readonly T1 m_Item1; // Do not rename (binary serialization) diff --git a/src/libraries/System.Private.CoreLib/src/System/Type.Enum.cs b/src/libraries/System.Private.CoreLib/src/System/Type.Enum.cs index d9885618c1288f..7793d2c50539c0 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Type.Enum.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Type.Enum.cs @@ -47,7 +47,7 @@ public virtual bool IsEnumDefined(object value) } // If an enum or integer value is passed in - if (Type.IsIntegerType(valueType)) + if (IsIntegerType(valueType)) { Type underlyingType = GetEnumUnderlyingType(); // We cannot compare the types directly because valueType is always a runtime type but underlyingType might not be. @@ -72,7 +72,7 @@ public virtual bool IsEnumDefined(object value) Type valueType = value.GetType(); - if (!(valueType.IsEnum || Type.IsIntegerType(valueType))) + if (!(valueType.IsEnum || IsIntegerType(valueType))) throw new ArgumentException(SR.Arg_MustBeEnumBaseTypeOrEnum, nameof(value)); Array values = GetEnumRawConstantValues(); diff --git a/src/libraries/System.Private.CoreLib/src/System/Type.cs b/src/libraries/System.Private.CoreLib/src/System/Type.cs index 8f6bb829b25908..7623274c457652 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Type.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Type.cs @@ -184,25 +184,25 @@ public ConstructorInfo? TypeInitializer public abstract ConstructorInfo[] GetConstructors(BindingFlags bindingAttr); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents)] - public EventInfo? GetEvent(string name) => GetEvent(name, Type.DefaultLookup); + public EventInfo? GetEvent(string name) => GetEvent(name, DefaultLookup); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)] public abstract EventInfo? GetEvent(string name, BindingFlags bindingAttr); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents)] - public virtual EventInfo[] GetEvents() => GetEvents(Type.DefaultLookup); + public virtual EventInfo[] GetEvents() => GetEvents(DefaultLookup); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicEvents | DynamicallyAccessedMemberTypes.NonPublicEvents)] public abstract EventInfo[] GetEvents(BindingFlags bindingAttr); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] - public FieldInfo? GetField(string name) => GetField(name, Type.DefaultLookup); + public FieldInfo? GetField(string name) => GetField(name, DefaultLookup); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] public abstract FieldInfo? GetField(string name, BindingFlags bindingAttr); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)] - public FieldInfo[] GetFields() => GetFields(Type.DefaultLookup); + public FieldInfo[] GetFields() => GetFields(DefaultLookup); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields | DynamicallyAccessedMemberTypes.NonPublicFields)] public abstract FieldInfo[] GetFields(BindingFlags bindingAttr); @@ -218,7 +218,7 @@ public ConstructorInfo? TypeInitializer DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicNestedTypes)] - public MemberInfo[] GetMember(string name) => GetMember(name, Type.DefaultLookup); + public MemberInfo[] GetMember(string name) => GetMember(name, DefaultLookup); [DynamicallyAccessedMembers(GetAllMembers)] public virtual MemberInfo[] GetMember(string name, BindingFlags bindingAttr) => GetMember(name, MemberTypes.All, bindingAttr); @@ -233,7 +233,7 @@ public ConstructorInfo? TypeInitializer DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.PublicNestedTypes)] - public MemberInfo[] GetMembers() => GetMembers(Type.DefaultLookup); + public MemberInfo[] GetMembers() => GetMembers(DefaultLookup); /// /// Searches for the on the current that matches the specified . @@ -271,7 +271,7 @@ private protected static ArgumentException CreateGetMemberWithSameMetadataDefini public abstract MemberInfo[] GetMembers(BindingFlags bindingAttr); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] - public MethodInfo? GetMethod(string name) => GetMethod(name, Type.DefaultLookup); + public MethodInfo? GetMethod(string name) => GetMethod(name, DefaultLookup); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] public MethodInfo? GetMethod(string name, BindingFlags bindingAttr) @@ -303,7 +303,7 @@ private protected static ArgumentException CreateGetMemberWithSameMetadataDefini public MethodInfo? GetMethod(string name, Type[] types) => GetMethod(name, types, null); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] - public MethodInfo? GetMethod(string name, Type[] types, ParameterModifier[]? modifiers) => GetMethod(name, Type.DefaultLookup, null, types, modifiers); + public MethodInfo? GetMethod(string name, Type[] types, ParameterModifier[]? modifiers) => GetMethod(name, DefaultLookup, null, types, modifiers); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] public MethodInfo? GetMethod(string name, BindingFlags bindingAttr, Binder? binder, Type[] types, ParameterModifier[]? modifiers) => GetMethod(name, bindingAttr, binder, CallingConventions.Any, types, modifiers); @@ -328,7 +328,7 @@ private protected static ArgumentException CreateGetMemberWithSameMetadataDefini public MethodInfo? GetMethod(string name, int genericParameterCount, Type[] types) => GetMethod(name, genericParameterCount, types, null); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] - public MethodInfo? GetMethod(string name, int genericParameterCount, Type[] types, ParameterModifier[]? modifiers) => GetMethod(name, genericParameterCount, Type.DefaultLookup, null, types, modifiers); + public MethodInfo? GetMethod(string name, int genericParameterCount, Type[] types, ParameterModifier[]? modifiers) => GetMethod(name, genericParameterCount, DefaultLookup, null, types, modifiers); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] public MethodInfo? GetMethod(string name, int genericParameterCount, BindingFlags bindingAttr, Binder? binder, Type[] types, ParameterModifier[]? modifiers) => GetMethod(name, genericParameterCount, bindingAttr, binder, CallingConventions.Any, types, modifiers); @@ -350,25 +350,25 @@ private protected static ArgumentException CreateGetMemberWithSameMetadataDefini protected virtual MethodInfo? GetMethodImpl(string name, int genericParameterCount, BindingFlags bindingAttr, Binder? binder, CallingConventions callConvention, Type[]? types, ParameterModifier[]? modifiers) => throw new NotSupportedException(); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] - public MethodInfo[] GetMethods() => GetMethods(Type.DefaultLookup); + public MethodInfo[] GetMethods() => GetMethods(DefaultLookup); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods | DynamicallyAccessedMemberTypes.NonPublicMethods)] public abstract MethodInfo[] GetMethods(BindingFlags bindingAttr); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes)] - public Type? GetNestedType(string name) => GetNestedType(name, Type.DefaultLookup); + public Type? GetNestedType(string name) => GetNestedType(name, DefaultLookup); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] public abstract Type? GetNestedType(string name, BindingFlags bindingAttr); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes)] - public Type[] GetNestedTypes() => GetNestedTypes(Type.DefaultLookup); + public Type[] GetNestedTypes() => GetNestedTypes(DefaultLookup); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicNestedTypes | DynamicallyAccessedMemberTypes.NonPublicNestedTypes)] public abstract Type[] GetNestedTypes(BindingFlags bindingAttr); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] - public PropertyInfo? GetProperty(string name) => GetProperty(name, Type.DefaultLookup); + public PropertyInfo? GetProperty(string name) => GetProperty(name, DefaultLookup); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] public PropertyInfo? GetProperty(string name, BindingFlags bindingAttr) @@ -385,7 +385,7 @@ private protected static ArgumentException CreateGetMemberWithSameMetadataDefini { ArgumentNullException.ThrowIfNull(name); - return GetPropertyImpl(name, Type.DefaultLookup, null, returnType, null, null); + return GetPropertyImpl(name, DefaultLookup, null, returnType, null, null); } [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] @@ -395,7 +395,7 @@ private protected static ArgumentException CreateGetMemberWithSameMetadataDefini public PropertyInfo? GetProperty(string name, Type? returnType, Type[] types) => GetProperty(name, returnType, types, null); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] - public PropertyInfo? GetProperty(string name, Type? returnType, Type[] types, ParameterModifier[]? modifiers) => GetProperty(name, Type.DefaultLookup, null, returnType, types, modifiers); + public PropertyInfo? GetProperty(string name, Type? returnType, Type[] types, ParameterModifier[]? modifiers) => GetProperty(name, DefaultLookup, null, returnType, types, modifiers); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] public PropertyInfo? GetProperty(string name, BindingFlags bindingAttr, Binder? binder, Type? returnType, Type[] types, ParameterModifier[]? modifiers) @@ -410,7 +410,7 @@ private protected static ArgumentException CreateGetMemberWithSameMetadataDefini protected abstract PropertyInfo? GetPropertyImpl(string name, BindingFlags bindingAttr, Binder? binder, Type? returnType, Type[]? types, ParameterModifier[]? modifiers); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties)] - public PropertyInfo[] GetProperties() => GetProperties(Type.DefaultLookup); + public PropertyInfo[] GetProperties() => GetProperties(DefaultLookup); [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicProperties | DynamicallyAccessedMemberTypes.NonPublicProperties)] public abstract PropertyInfo[] GetProperties(BindingFlags bindingAttr); @@ -644,16 +644,16 @@ internal string FormatTypeName() public override int GetHashCode() { Type systemType = UnderlyingSystemType; - if (!object.ReferenceEquals(systemType, this)) + if (!ReferenceEquals(systemType, this)) return systemType.GetHashCode(); return base.GetHashCode(); } - public virtual bool Equals(Type? o) => o == null ? false : object.ReferenceEquals(this.UnderlyingSystemType, o.UnderlyingSystemType); + public virtual bool Equals(Type? o) => o == null ? false : ReferenceEquals(this.UnderlyingSystemType, o.UnderlyingSystemType); [Intrinsic] public static bool operator ==(Type? left, Type? right) { - if (object.ReferenceEquals(left, right)) + if (ReferenceEquals(left, right)) return true; // Runtime types are never equal to non-runtime types @@ -691,7 +691,7 @@ public static Binder DefaultBinder public static readonly char Delimiter = '.'; public static readonly Type[] EmptyTypes = Array.Empty(); - public static readonly object Missing = System.Reflection.Missing.Value; + public static readonly object Missing = Reflection.Missing.Value; public static readonly MemberFilter FilterAttribute = FilterAttributeImpl!; public static readonly MemberFilter FilterName = (m, c) => FilterNameImpl(m, c!, StringComparison.Ordinal); diff --git a/src/libraries/System.Private.CoreLib/src/System/TypeAccessException.cs b/src/libraries/System.Private.CoreLib/src/System/TypeAccessException.cs index 16b6aa7c89410b..4068ac3b816025 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TypeAccessException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TypeAccessException.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System @@ -9,7 +10,7 @@ namespace System // TypeAccessException derives from TypeLoadException rather than MemberAccessException because in // pre-v4 releases of the runtime TypeLoadException was used in lieu of a TypeAccessException. [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class TypeAccessException : TypeLoadException { public TypeAccessException() diff --git a/src/libraries/System.Private.CoreLib/src/System/TypeInitializationException.cs b/src/libraries/System.Private.CoreLib/src/System/TypeInitializationException.cs index 7e71dad29fb400..97efd804c3c8bb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TypeInitializationException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TypeInitializationException.cs @@ -14,12 +14,13 @@ =============================================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public sealed class TypeInitializationException : SystemException { private readonly string? _typeName; diff --git a/src/libraries/System.Private.CoreLib/src/System/TypeLoadException.cs b/src/libraries/System.Private.CoreLib/src/System/TypeLoadException.cs index 9ac7ff2efc1f9f..f588f3d23f0ff4 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TypeLoadException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TypeLoadException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public partial class TypeLoadException : SystemException { public TypeLoadException() diff --git a/src/libraries/System.Private.CoreLib/src/System/TypeUnloadedException.cs b/src/libraries/System.Private.CoreLib/src/System/TypeUnloadedException.cs index 31ef328977f32c..aff385f678bfd5 100644 --- a/src/libraries/System.Private.CoreLib/src/System/TypeUnloadedException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/TypeUnloadedException.cs @@ -2,12 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class TypeUnloadedException : SystemException { public TypeUnloadedException() diff --git a/src/libraries/System.Private.CoreLib/src/System/UnauthorizedAccessException.cs b/src/libraries/System.Private.CoreLib/src/System/UnauthorizedAccessException.cs index b57da7c36c30bd..395c578f19279f 100644 --- a/src/libraries/System.Private.CoreLib/src/System/UnauthorizedAccessException.cs +++ b/src/libraries/System.Private.CoreLib/src/System/UnauthorizedAccessException.cs @@ -13,6 +13,7 @@ ===========================================================*/ using System.ComponentModel; +using System.Runtime.CompilerServices; using System.Runtime.Serialization; namespace System @@ -20,7 +21,7 @@ namespace System // The UnauthorizedAccessException is thrown when access errors // occur from IO or other OS methods. [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public class UnauthorizedAccessException : SystemException { public UnauthorizedAccessException() diff --git a/src/libraries/System.Private.CoreLib/src/System/ValueTuple.cs b/src/libraries/System.Private.CoreLib/src/System/ValueTuple.cs index 5415a61d790765..240ad862ffcf24 100644 --- a/src/libraries/System.Private.CoreLib/src/System/ValueTuple.cs +++ b/src/libraries/System.Private.CoreLib/src/System/ValueTuple.cs @@ -30,7 +30,7 @@ internal interface IValueTupleInternal : ITuple /// - their members (such as Item1, Item2, etc) are fields rather than properties. /// [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public struct ValueTuple : IEquatable, IStructuralEquatable, IStructuralComparable, IComparable, IComparable, IValueTupleInternal, ITuple { @@ -253,13 +253,13 @@ public static ValueTuple CreateThe value of the eighth component of the tuple. /// An 8-tuple (octuple) whose value is (item1, item2, item3, item4, item5, item6, item7, item8). public static ValueTuple> Create(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, T8 item8) => - new ValueTuple>(item1, item2, item3, item4, item5, item6, item7, ValueTuple.Create(item8)); + new ValueTuple>(item1, item2, item3, item4, item5, item6, item7, Create(item8)); } /// Represents a 1-tuple, or singleton, as a value type. /// The type of the tuple's only component. [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public struct ValueTuple : IEquatable>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable>, IValueTupleInternal, ITuple { @@ -423,7 +423,7 @@ string IValueTupleInternal.ToStringEnd() /// The type of the tuple's second component. [Serializable] [StructLayout(LayoutKind.Auto)] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public struct ValueTuple : IEquatable>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable>, IValueTupleInternal, ITuple { @@ -625,7 +625,7 @@ string IValueTupleInternal.ToStringEnd() /// The type of the tuple's third component. [Serializable] [StructLayout(LayoutKind.Auto)] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public struct ValueTuple : IEquatable>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable>, IValueTupleInternal, ITuple { @@ -824,7 +824,7 @@ string IValueTupleInternal.ToStringEnd() /// The type of the tuple's fourth component. [Serializable] [StructLayout(LayoutKind.Auto)] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public struct ValueTuple : IEquatable>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable>, IValueTupleInternal, ITuple { @@ -1041,7 +1041,7 @@ string IValueTupleInternal.ToStringEnd() /// The type of the tuple's fifth component. [Serializable] [StructLayout(LayoutKind.Auto)] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public struct ValueTuple : IEquatable>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable>, IValueTupleInternal, ITuple { @@ -1275,7 +1275,7 @@ string IValueTupleInternal.ToStringEnd() /// The type of the tuple's sixth component. [Serializable] [StructLayout(LayoutKind.Auto)] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public struct ValueTuple : IEquatable>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable>, IValueTupleInternal, ITuple { @@ -1527,7 +1527,7 @@ string IValueTupleInternal.ToStringEnd() /// The type of the tuple's seventh component. [Serializable] [StructLayout(LayoutKind.Auto)] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public struct ValueTuple : IEquatable>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable>, IValueTupleInternal, ITuple { @@ -1797,7 +1797,7 @@ string IValueTupleInternal.ToStringEnd() /// The type of the tuple's eighth component. [Serializable] [StructLayout(LayoutKind.Auto)] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public struct ValueTuple : IEquatable>, IStructuralEquatable, IStructuralComparable, IComparable, IComparable>, IValueTupleInternal, ITuple where TRest : struct diff --git a/src/libraries/System.Private.CoreLib/src/System/Version.cs b/src/libraries/System.Private.CoreLib/src/System/Version.cs index 2b13e362ee3a57..df02ca3368c11b 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Version.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Version.cs @@ -65,7 +65,7 @@ public Version(int major, int minor) public Version(string version) { - Version v = Version.Parse(version); + Version v = Parse(version); _Major = v.Major; _Minor = v.Minor; _Build = v.Build; @@ -126,7 +126,7 @@ public int CompareTo(object? version) public int CompareTo(Version? value) { return - object.ReferenceEquals(value, this) ? 0 : + ReferenceEquals(value, this) ? 0 : value is null ? 1 : _Major != value._Major ? (_Major > value._Major ? 1 : -1) : _Minor != value._Minor ? (_Minor > value._Minor ? 1 : -1) : @@ -142,7 +142,7 @@ public override bool Equals([NotNullWhen(true)] object? obj) public bool Equals([NotNullWhen(true)] Version? obj) { - return object.ReferenceEquals(obj, this) || + return ReferenceEquals(obj, this) || (!(obj is null) && _Major == obj._Major && _Minor == obj._Minor && diff --git a/src/libraries/System.Private.CoreLib/src/System/WeakReference.T.cs b/src/libraries/System.Private.CoreLib/src/System/WeakReference.T.cs index 5bc19e32b6e9a8..8ddca591075a0c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/WeakReference.T.cs +++ b/src/libraries/System.Private.CoreLib/src/System/WeakReference.T.cs @@ -13,7 +13,7 @@ namespace System { [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] // This class is sealed to mitigate security issues caused by Object::MemberwiseClone. public sealed partial class WeakReference : ISerializable where T : class? diff --git a/src/libraries/System.Private.CoreLib/src/System/WeakReference.cs b/src/libraries/System.Private.CoreLib/src/System/WeakReference.cs index 5f4079183edfa8..932dcb0220db7c 100644 --- a/src/libraries/System.Private.CoreLib/src/System/WeakReference.cs +++ b/src/libraries/System.Private.CoreLib/src/System/WeakReference.cs @@ -28,7 +28,7 @@ internal static class WeakReferenceHandleTags } [Serializable] - [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] + [TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] public partial class WeakReference : ISerializable { // If you fix bugs here, please fix them in WeakReference at the same time. diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaValidator.cs b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaValidator.cs index e2eabb8a0c711c..913c2e92376212 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaValidator.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Schema/XmlSchemaValidator.cs @@ -2596,7 +2596,7 @@ internal static string PrintExpectedElements(ArrayList expected, bool getParticl { if (getParticles) { - string ContinuationString = SR.Format(SR.Sch_ContinuationString, new string[] { " " }); + string ContinuationString = SR.Format(SR.Sch_ContinuationString, " "); XmlSchemaParticle? currentParticle; XmlSchemaParticle? nextParticle = null; XmlQualifiedName currentQName; diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationILGen.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationILGen.cs index e35719e7c00731..a44d9571841b8b 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationILGen.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationILGen.cs @@ -65,6 +65,15 @@ internal ModuleBuilder ModuleBuilder } internal TypeAttributes TypeAttributes { get { return _typeAttributes; } } + private static readonly string[] s_typeString = new string[] { "type" }; + private static readonly string[] s_xmlReaderString = new string[] { "xmlReader" }; + private static readonly string[] s_objectToSerializeWriterString = new string[] { "objectToSerialize", "writer" }; + private static readonly string[] s_readerString = new string[] { "reader" }; + private static readonly Type[] s_typeType = new Type[] { typeof(Type) }; + private static readonly Type[] s_xmlReaderType = new Type[] { typeof(XmlReader) }; + private static readonly Type[] s_objectXmlSerializationWriterType = new Type[] { typeof(object), typeof(XmlSerializationWriter) }; + private static readonly Type[] s_xmlSerializationReaderType = new Type[] { typeof(XmlSerializationReader) }; + internal MethodBuilder EnsureMethodBuilder(TypeBuilder typeBuilder, string methodName, MethodAttributes attributes, Type? returnType, Type[] parameterTypes) { @@ -228,8 +237,8 @@ internal void GenerateSupportedTypes(Type[] types, TypeBuilder serializerContrac ilg.BeginMethod( typeof(bool), "CanSerialize", - new Type[] { typeof(Type) }, - new string[] { "type" }, + s_typeType, + s_typeString, CodeGenerator.PublicOverrideMethodAttributes); var uniqueTypes = new HashSet(); for (int i = 0; i < types.Length; i++) @@ -323,8 +332,8 @@ internal string GenerateTypedSerializer(string readMethod, string writeMethod, X ilg.BeginMethod( typeof(bool), "CanDeserialize", - new Type[] { typeof(XmlReader) }, - new string[] { "xmlReader" }, + s_xmlReaderType, + s_xmlReaderString, CodeGenerator.PublicOverrideMethodAttributes ); @@ -358,8 +367,8 @@ internal string GenerateTypedSerializer(string readMethod, string writeMethod, X ilg.BeginMethod( typeof(void), "Serialize", - new Type[] { typeof(object), typeof(XmlSerializationWriter) }, - new string[] { "objectToSerialize", "writer" }, + s_objectXmlSerializationWriterType, + s_objectToSerializeWriterString, CodeGenerator.ProtectedOverrideMethodAttributes); MethodInfo writerType_writeMethod = CreatedTypes[writerClass].GetMethod( writeMethod, @@ -382,8 +391,8 @@ internal string GenerateTypedSerializer(string readMethod, string writeMethod, X ilg.BeginMethod( typeof(object), "Deserialize", - new Type[] { typeof(XmlSerializationReader) }, - new string[] { "reader" }, + s_xmlSerializationReaderType, + s_readerString, CodeGenerator.ProtectedOverrideMethodAttributes); MethodInfo readerType_readMethod = CreatedTypes[readerClass].GetMethod( readMethod, @@ -436,8 +445,8 @@ private void GenerateGetSerializer(Dictionary serializers, XmlMa ilg.BeginMethod( typeof(XmlSerializer), "GetSerializer", - new Type[] { typeof(Type) }, - new string[] { "type" }, + s_typeType, + s_typeString, CodeGenerator.PublicOverrideMethodAttributes); for (int i = 0; i < xmlMappings.Length; i++) diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationReaderILGen.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationReaderILGen.cs index de61c280637a42..6db572452ea0ba 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationReaderILGen.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationReaderILGen.cs @@ -26,6 +26,9 @@ internal sealed partial class XmlSerializationReaderILGen : XmlSerializationILGe internal Dictionary Enums => _enums ??= new Dictionary(); + private static readonly string[] s_checkTypeString = new string[] { "checkType" }; + private static readonly Type[] s_boolType = new Type[] { typeof(bool) }; + private sealed class Member { private readonly string _source; @@ -503,7 +506,7 @@ private string GenerateLiteralMembersElement(XmlMembersMapping xmlMembersMapping MethodInfo XmlSerializationReader_set_IsReturnValue = typeof(XmlSerializationReader).GetMethod( "set_IsReturnValue", CodeGenerator.InstanceBindingFlags, - new Type[] { typeof(bool) } + s_boolType )!; ilg.Ldarg(0); ilg.Ldc(true); @@ -1289,8 +1292,8 @@ private void WriteNullableMethod(NullableMapping nullableMapping) ilg.BeginMethod( nullableMapping.TypeDesc!.Type!, GetMethodBuilder(methodName!), - new Type[] { typeof(bool) }, - new string[] { "checkType" }, + s_boolType, + s_checkTypeString, CodeGenerator.PrivateMethodAttributes); LocalBuilder oLoc = ilg.DeclareLocal(nullableMapping.TypeDesc.Type!, "o"); @@ -1525,7 +1528,7 @@ private void WriteLiteralStructMethod(StructMapping structMapping) MethodInfo XmlSerializationReader_set_DecodeName = typeof(XmlSerializationReader).GetMethod( "set_DecodeName", CodeGenerator.InstanceBindingFlags, - new Type[] { typeof(bool) } + s_boolType )!; ilg.Ldarg(0); ilg.Ldc(false); @@ -2559,7 +2562,7 @@ private void WriteMemberElementsIf(Member[] members, Member? anyElement, string MethodInfo XmlSerializationReader_set_IsReturnValue = typeof(XmlSerializationReader).GetMethod( "set_IsReturnValue", CodeGenerator.InstanceBindingFlags, - new Type[] { typeof(bool) } + s_boolType )!; ilg.Ldarg(0); ilg.Ldc(false); @@ -3015,7 +3018,7 @@ private void WriteElement(string source, string? arrayName, string? choiceSource CodeGenerator.PrivateMethodAttributes, // See WriteNullableMethod for different return type logic element.Mapping.TypeDesc!.Type, - new Type[] { typeof(bool) } + s_boolType ); ilg.Call(methodBuilder); WriteSourceEnd(source, element.Mapping.TypeDesc.Type!); @@ -3209,7 +3212,7 @@ private void WriteElement(string source, string? arrayName, string? choiceSource MethodInfo XmlSerializationReader_ReadXmlXXX = typeof(XmlSerializationReader).GetMethod( isDoc ? "ReadXmlDocument" : "ReadXmlNode", CodeGenerator.InstanceBindingFlags, - new Type[] { typeof(bool) } + s_boolType )!; ilg.Ldarg(0); ilg.Ldc(element.Any ? false : true); diff --git a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationWriterILGen.cs b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationWriterILGen.cs index 86048ea3287bd1..81f9462a26a7a2 100644 --- a/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationWriterILGen.cs +++ b/src/libraries/System.Private.Xml/src/System/Xml/Serialization/XmlSerializationWriterILGen.cs @@ -332,7 +332,7 @@ private void WriteEndElement(string source) MethodInfo XmlSerializationWriter_WriteEndElement = typeof(XmlSerializationWriter).GetMethod( "WriteEndElement", CodeGenerator.InstanceBindingFlags, - new Type[] { typeof(object) } + s_objectType )!; object oVar = ilg.GetVariable(source); ilg.Ldarg(0); @@ -353,6 +353,11 @@ private void WriteEmptyTag(string name, string? ns) WriteTag("WriteEmptyTag", name, ns); } + private static readonly string[] s_argNamesP = new string[] { "p" }; + private static readonly string[] s_argNamesO = new string[] { "o" }; + private static readonly Type[] s_objectArrayType = new Type[] { typeof(object[]) }; + private static readonly Type[] s_objectType = new Type[] { typeof(object) }; + [RequiresUnreferencedCode("calls WriteMember")] private string GenerateMembersElement(XmlMembersMapping xmlMembersMapping) { @@ -365,8 +370,8 @@ private string GenerateMembersElement(XmlMembersMapping xmlMembersMapping) ilg.BeginMethod( typeof(void), methodName, - new Type[] { typeof(object[]) }, - new string[] { "p" }, + s_objectArrayType, + s_argNamesP, CodeGenerator.PublicMethodAttributes ); @@ -557,8 +562,8 @@ private string GenerateTypeElement(XmlTypeMapping xmlTypeMapping) ilg.BeginMethod( typeof(void), methodName, - new Type[] { typeof(object) }, - new string[] { "o" }, + s_objectType, + s_argNamesO, CodeGenerator.PublicMethodAttributes ); @@ -1004,7 +1009,7 @@ private void WriteStructMethod(StructMapping mapping) MethodInfo XmlSerializationWriter_CreateUnknownTypeException = typeof(XmlSerializationWriter).GetMethod( "CreateUnknownTypeException", CodeGenerator.InstanceBindingFlags, - new Type[] { typeof(object) } + s_objectType )!; ilg.Ldarg(0); ilg.Ldarg(oArg); @@ -1849,7 +1854,7 @@ private void WriteElements(SourceInfo source, string? enumSource, ElementAccesso MethodInfo XmlSerializationWriter_CreateUnknownTypeException = typeof(XmlSerializationWriter).GetMethod( "CreateUnknownTypeException", CodeGenerator.InstanceBindingFlags, - new Type[] { typeof(object) })!; + s_objectType)!; ilg.Ldarg(0); source.Load(typeof(object)); ilg.Call(XmlSerializationWriter_CreateUnknownTypeException); @@ -2064,7 +2069,7 @@ private void WriteElement(SourceInfo source, ElementAccessor element, string arr MethodInfo XmlSerializationWriter_CreateInvalidAnyTypeException = typeof(XmlSerializationWriter).GetMethod( "CreateInvalidAnyTypeException", CodeGenerator.InstanceBindingFlags, - new Type[] { typeof(object) } + s_objectType )!; ilg.Ldarg(0); source.Load(null); diff --git a/src/libraries/System.Reflection.Context/src/Resources/Strings.resx b/src/libraries/System.Reflection.Context/src/Resources/Strings.resx index 3b0d6ec30a2a62..275355e7de70ee 100644 --- a/src/libraries/System.Reflection.Context/src/Resources/Strings.resx +++ b/src/libraries/System.Reflection.Context/src/Resources/Strings.resx @@ -108,4 +108,7 @@ Object of type '{0}' cannot be converted to type '{1}'. - \ No newline at end of file + + Ambiguous match found for '{0} {1}'. + + diff --git a/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Custom/CustomType.cs b/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Custom/CustomType.cs index 543e113748995d..95ee34ab4504b6 100644 --- a/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Custom/CustomType.cs +++ b/src/libraries/System.Reflection.Context/src/System/Reflection/Context/Custom/CustomType.cs @@ -257,7 +257,6 @@ public override MethodInfo[] GetMethods(BindingFlags bindingAttr) } } - if (matchingMethods.Count == 0) return null; @@ -266,10 +265,12 @@ public override MethodInfo[] GetMethods(BindingFlags bindingAttr) Debug.Assert(types == null || types.Length == 0); // matches any signature + MethodInfo match = matchingMethods[0]; if (matchingMethods.Count == 1) - return matchingMethods[0]; - else - throw new AmbiguousMatchException(); + return match; + + Type? declaringType = match.DeclaringType; + throw new AmbiguousMatchException(SR.Format(SR.Arg_AmbiguousMatchException_MemberInfo, declaringType, match)); } else { diff --git a/src/libraries/System.Reflection.Emit/tests/ConstructorBuilder/ConstructorBuilderGetILGenerator.cs b/src/libraries/System.Reflection.Emit/tests/ConstructorBuilder/ConstructorBuilderGetILGenerator.cs index a9cf9e2b8e91f9..f4999edefc37a6 100644 --- a/src/libraries/System.Reflection.Emit/tests/ConstructorBuilder/ConstructorBuilderGetILGenerator.cs +++ b/src/libraries/System.Reflection.Emit/tests/ConstructorBuilder/ConstructorBuilderGetILGenerator.cs @@ -52,5 +52,40 @@ public void GetILGenerator_DefaultConstructor_ThrowsInvalidOperationException() Assert.Throws(() => constructor.GetILGenerator()); Assert.Throws(() => constructor.GetILGenerator(10)); } + + [Fact] + public void HasDefaultValueShouldBeFalseWhenParameterDoNotDefineDefaultValue() + { + var builder = Helpers.DynamicModule(); + var type = builder.DefineType("MyProxy", TypeAttributes.Public); + + var constructorBuilder = type.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new[] { typeof(Version) }); + var il = constructorBuilder.GetILGenerator(); + il.Emit(OpCodes.Ret); + + var typeInfo = type.CreateTypeInfo(); + var constructor = typeInfo.GetConstructor(new[] { typeof(Version) }); + var parameters = constructor.GetParameters(); + Assert.False(parameters[0].HasDefaultValue); + } + + [Fact] + public void HasDefaultValueShouldBeTrueWhenParameterDoDefineDefaultValue() + { + var builder = Helpers.DynamicModule(); + var type = builder.DefineType("MyProxy", TypeAttributes.Public); + + var constructorBuilder = type.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new[] { typeof(Version) }); + ParameterBuilder parameter = constructorBuilder.DefineParameter(1, ParameterAttributes.Optional | ParameterAttributes.HasDefault, "param1"); + parameter.SetConstant(default(Version)); + var il = constructorBuilder.GetILGenerator(); + il.Emit(OpCodes.Ret); + + var typeInfo = type.CreateTypeInfo(); + var constructor = typeInfo.GetConstructor(new[] { typeof(Version) }); + var parameters = constructor.GetParameters(); + Assert.True(parameters[0].HasDefaultValue); + Assert.Null(parameters[0].DefaultValue); + } } } diff --git a/src/libraries/System.Reflection.Emit/tests/MethodBuilder/MethodBuilderGetILGenerator.cs b/src/libraries/System.Reflection.Emit/tests/MethodBuilder/MethodBuilderGetILGenerator.cs index 2ac6b45825a19b..2ce5cab8152e20 100644 --- a/src/libraries/System.Reflection.Emit/tests/MethodBuilder/MethodBuilderGetILGenerator.cs +++ b/src/libraries/System.Reflection.Emit/tests/MethodBuilder/MethodBuilderGetILGenerator.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 Microsoft.Diagnostics.Runtime.Interop; using Xunit; namespace System.Reflection.Emit.Tests @@ -140,5 +139,40 @@ public void LoadByRefTypeInILGeneratedMethod() MethodInfo createdMethod = createdType.GetMethod("TestMethod"); Assert.Equal("TestType&", createdMethod.Invoke(null, null)); } + + [Fact] + public void HasDefaultValueShouldBeFalseWhenParameterDoNotDefineDefaultValue() + { + var builder = Helpers.DynamicModule(); + var type = builder.DefineType("MyProxy", TypeAttributes.Public); + + var methodBuilder = type.DefineMethod("DoSomething", MethodAttributes.Public, CallingConventions.Standard, typeof(void), new[] { typeof(Version) }); + var il = methodBuilder.GetILGenerator(); + il.Emit(OpCodes.Ret); + + var typeInfo = type.CreateTypeInfo(); + var method = typeInfo.GetMethod("DoSomething", new[] { typeof(Version) }); + var parameters = method.GetParameters(); + Assert.False(parameters[0].HasDefaultValue); + } + + [Fact] + public void HasDefaultValueShouldBeTrueWhenParameterDoDefineDefaultValue() + { + var builder = Helpers.DynamicModule(); + var type = builder.DefineType("MyProxy", TypeAttributes.Public); + + var methodBuilder = type.DefineMethod("DoSomething", MethodAttributes.Public, CallingConventions.Standard, typeof(void), new[] { typeof(Version) }); + ParameterBuilder parameter = methodBuilder.DefineParameter(1, ParameterAttributes.Optional | ParameterAttributes.HasDefault, "param1"); + parameter.SetConstant(default(Version)); + var il = methodBuilder.GetILGenerator(); + il.Emit(OpCodes.Ret); + + var typeInfo = type.CreateTypeInfo(); + var method = typeInfo.GetMethod("DoSomething", new[] { typeof(Version) }); + var parameters = method.GetParameters(); + Assert.True(parameters[0].HasDefaultValue); + Assert.Null(parameters[0].DefaultValue); + } } } diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/Resources/Strings.resx b/src/libraries/System.Reflection.MetadataLoadContext/src/Resources/Strings.resx index 4412920b3cdf8d..2f48f0bd2ce47b 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/Resources/Strings.resx +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/Resources/Strings.resx @@ -270,4 +270,10 @@ The path '{0}' is not valid. - \ No newline at end of file + + Ambiguous match found for '{0}'. + + + Ambiguous match found for '{0} {1}'. + + diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj b/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj index fb84ae946b87e5..76d07ddacf18dc 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System.Reflection.MetadataLoadContext.csproj @@ -147,6 +147,7 @@ + diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/DefaultBinder.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/DefaultBinder.cs index e74384109ba342..10501e11c4a4ac 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/DefaultBinder.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/DefaultBinder.cs @@ -137,9 +137,10 @@ public sealed override MethodBase BindToMethod( ambig = false; } } + MethodBase bestMatch = candidates[currentMin]; if (ambig) - throw new AmbiguousMatchException(); - return candidates[currentMin]; + throw ThrowHelper.GetAmbiguousMatchException(bestMatch); + return bestMatch; } // Given a set of properties that match the base criteria, select one. @@ -256,9 +257,10 @@ public sealed override MethodBase BindToMethod( } } + PropertyInfo bestMatch = candidates[currentMin]; if (ambig) - throw new AmbiguousMatchException(); - return candidates[currentMin]; + throw ThrowHelper.GetAmbiguousMatchException(bestMatch); + return bestMatch; } // The default binder doesn't support any change type functionality. @@ -341,7 +343,7 @@ public sealed override MethodBase BindToMethod( continue; if (bestMatch != null) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(bestMatch); bestMatch = match[i]; } @@ -606,7 +608,7 @@ private static int GetHierarchyDepth(Type t) // This can only happen if at least one is vararg or generic. if (currentHierarchyDepth == deepestHierarchy) { - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(methWithDeepestHierarchy!); } // Check to see if this method is on the most derived class. diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/Runtime/BindingFlagSupport/QueryResult.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/Runtime/BindingFlagSupport/QueryResult.cs index f90ff00c6c4a1f..74ace1ca538ac3 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/Runtime/BindingFlagSupport/QueryResult.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/Runtime/BindingFlagSupport/QueryResult.cs @@ -112,11 +112,11 @@ public void CopyTo(MemberInfo[] array, int startIndex) // declared by the most derived type. Since QueriedMemberLists are sorted in order of decreasing derivation, // that means we let the first match win - unless, of course, they're both the "most derived member". if (match.DeclaringType!.Equals(challenger.DeclaringType)) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(match); MemberPolicies policies = MemberPolicies.Default; if (!policies.OkToIgnoreAmbiguity(match, challenger)) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(match); } else { diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/CustomAttributes/CustomAttributeHelpers.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/CustomAttributes/CustomAttributeHelpers.cs index 56d7bfbf3a6cf2..745b5d13c7cdf7 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/CustomAttributes/CustomAttributeHelpers.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/CustomAttributes/CustomAttributeHelpers.cs @@ -17,10 +17,10 @@ public static CustomAttributeNamedArgument ToCustomAttributeNamedArgument(this T MemberInfo[] members = attributeType.GetMember(name, MemberTypes.Field | MemberTypes.Property, BindingFlags.Public | BindingFlags.Instance); if (members.Length == 0) throw new MissingMemberException(attributeType.FullName, name); + MemberInfo match = members[0]; if (members.Length > 1) - throw new AmbiguousMatchException(); - - return new CustomAttributeNamedArgument(members[0], new CustomAttributeTypedArgument(argumentType!, value)); + throw ThrowHelper.GetAmbiguousMatchException(match); + return new CustomAttributeNamedArgument(match, new CustomAttributeTypedArgument(argumentType!, value)); } /// diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/RuntimeTypeInfo.BindingFlags.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/RuntimeTypeInfo.BindingFlags.cs index 247379c22f4bf5..ed9d80059b22b0 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/RuntimeTypeInfo.BindingFlags.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/RuntimeTypeInfo.BindingFlags.cs @@ -136,10 +136,11 @@ internal partial class RoType // For perf and .NET Framework compat, fast-path these specific checks before calling on the binder to break ties. if (types == null || types.Length == 0) { + PropertyInfo firstCandidate = candidates[0]; + // no arguments if (candidates.Count == 1) { - PropertyInfo firstCandidate = candidates[0]; if (!(returnType is null) && !returnType.IsEquivalentTo(firstCandidate.PropertyType)) return null; return firstCandidate; @@ -148,7 +149,7 @@ internal partial class RoType { if (returnType is null) // if we are here we have no args or property type to select over and we have more than one property with that name - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(firstCandidate); } } diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/Ecma/EcmaDefinitionType.BindingFlags.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/Ecma/EcmaDefinitionType.BindingFlags.cs index 099c52d3b33265..cf194198064c03 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/Ecma/EcmaDefinitionType.BindingFlags.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/Ecma/EcmaDefinitionType.BindingFlags.cs @@ -94,7 +94,7 @@ internal sealed override IEnumerable GetNestedTypesCore(NameFilter? filt if (nestedTypeDefinition.Name.Equals(utf8Name, reader)) { if (match != null) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(match); match = handle.ResolveTypeDef(GetEcmaModule()); } } diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoType.GetInterface.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoType.GetInterface.cs index 60530bb16fa71f..e9d9881cc52bc4 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoType.GetInterface.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/Types/RoType.GetInterface.cs @@ -33,7 +33,7 @@ internal partial class RoType if (ns.Length != 0 && !ns.Equals(ifc.Namespace)) continue; if (match != null) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(match); match = ifc; } return match; diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/ThrowHelper.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/ThrowHelper.cs new file mode 100644 index 00000000000000..0b28c0cf90532a --- /dev/null +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/ThrowHelper.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. + +// This file defines an internal static class used to throw exceptions in the +// the System.Reflection.MetadataLoadContext code. + +using System.Reflection; +using System.Reflection.TypeLoading; + +namespace System +{ + internal static class ThrowHelper + { + internal static AmbiguousMatchException GetAmbiguousMatchException(RoDefinitionType roDefinitionType) + { + return new AmbiguousMatchException(SR.Format(SR.Arg_AmbiguousMatchException_RoDefinitionType, roDefinitionType.FullName)); + } + + internal static AmbiguousMatchException GetAmbiguousMatchException(MemberInfo memberInfo) + { + Type? declaringType = memberInfo.DeclaringType; + return new AmbiguousMatchException(SR.Format(SR.Arg_AmbiguousMatchException_MemberInfo, declaringType, memberInfo)); + } + } +} diff --git a/src/libraries/System.Reflection/tests/ParameterInfoTests.cs b/src/libraries/System.Reflection/tests/ParameterInfoTests.cs index 81200b6040d360..50aba566353d21 100644 --- a/src/libraries/System.Reflection/tests/ParameterInfoTests.cs +++ b/src/libraries/System.Reflection/tests/ParameterInfoTests.cs @@ -83,7 +83,7 @@ public void HasDefaultValue_broken_on_NETFX(Type type, string name, int index, b public void HasDefaultValue_ReturnParam() { ParameterInfo parameterInfo = GetMethod(typeof(ParameterInfoMetadata), "Method1").ReturnParameter; - Assert.True(parameterInfo.HasDefaultValue); + Assert.False(parameterInfo.HasDefaultValue); } [Theory] diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.sln b/src/libraries/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.sln index 42259595f8f33e..d8ed34f2b917d3 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.sln +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/System.Runtime.InteropServices.JavaScript.sln @@ -11,7 +11,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.InteropServi EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JSImportGenerator.Unit.Tests", "tests\JSImportGenerator.UnitTest\JSImportGenerator.Unit.Tests.csproj", "{BFED925C-18F2-4C98-833E-66F205234598}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.InteropServices.JavaScript.Legacy.UnitTests", "tests\System.Runtime.InteropServices.JavaScript.Legacy.UnitTests\System.Runtime.InteropServices.JavaScript.Legacy.UnitTests.csproj", "{ABA5A92B-CAD8-47E8-A7CE-D28A67FB69C0}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.InteropServices.JavaScript.Legacy.UnitTests", "tests\System.Runtime.InteropServices.JavaScript.Legacy.UnitTests\System.Runtime.InteropServices.JavaScript.Legacy.Tests.csproj", "{ABA5A92B-CAD8-47E8-A7CE-D28A67FB69C0}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.Runtime.InteropServices.JavaScript.Tests", "tests\System.Runtime.InteropServices.JavaScript.UnitTests\System.Runtime.InteropServices.JavaScript.Tests.csproj", "{765B4AA5-723A-44FF-BC4E-EB0F03103F6D}" EndProject diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Comparers.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Comparers.cs index 495deb4638662f..f27af1ccd55645 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Comparers.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/Comparers.cs @@ -15,11 +15,11 @@ internal static class Comparers /// /// Comparer for an individual generated stub source as a syntax tree and the generated diagnostics for the stub. /// - public static readonly IEqualityComparer<(MemberDeclarationSyntax Syntax, ImmutableArray Diagnostics)> GeneratedSyntax = new CustomValueTupleElementComparer>(SyntaxEquivalentComparer.Instance, new ImmutableArraySequenceEqualComparer(EqualityComparer.Default)); - public static readonly IEqualityComparer<(MemberDeclarationSyntax, StatementSyntax, AttributeListSyntax, ImmutableArray)> GeneratedSyntax4 = - new CustomValueTupleElementComparer>( + public static readonly IEqualityComparer<(MemberDeclarationSyntax Syntax, ImmutableArray Diagnostics)> GeneratedSyntax = new CustomValueTupleElementComparer>(SyntaxEquivalentComparer.Instance, new ImmutableArraySequenceEqualComparer(EqualityComparer.Default)); + public static readonly IEqualityComparer<(MemberDeclarationSyntax, StatementSyntax, AttributeListSyntax, ImmutableArray)> GeneratedSyntax4 = + new CustomValueTupleElementComparer>( SyntaxEquivalentComparer.Instance, SyntaxEquivalentComparer.Instance, SyntaxEquivalentComparer.Instance, - new ImmutableArraySequenceEqualComparer(EqualityComparer.Default)); + new ImmutableArraySequenceEqualComparer(EqualityComparer.Default)); } /// diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/GeneratorDiagnostics.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/GeneratorDiagnostics.cs index fea0a917cf5b1e..1cd066f0d9255b 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/GeneratorDiagnostics.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/GeneratorDiagnostics.cs @@ -28,9 +28,9 @@ public class Ids } private const string Category = "JSImportGenerator"; - private readonly List _diagnostics = new List(); + private readonly List _diagnostics = new List(); - public IEnumerable Diagnostics => _diagnostics; + public IEnumerable Diagnostics => _diagnostics; public void ReportInvalidMarshallingAttributeInfo( AttributeData attributeData, @@ -38,7 +38,7 @@ public void ReportInvalidMarshallingAttributeInfo( params string[] reasonArgs) { _diagnostics.Add( - attributeData.CreateDiagnostic( + attributeData.CreateDiagnosticInfo( GeneratorDiagnostics.MarshallingAttributeConfigurationNotSupported, new LocalizableResourceString(reasonResourceName, SR.ResourceManager, typeof(FxResources.Microsoft.Interop.JavaScript.JSImportGenerator.SR), reasonArgs))); } @@ -57,14 +57,14 @@ public void ReportConfigurationNotSupported( if (unsupportedValue == null) { _diagnostics.Add( - attributeData.CreateDiagnostic( + attributeData.CreateDiagnosticInfo( GeneratorDiagnostics.ConfigurationNotSupported, configurationName)); } else { _diagnostics.Add( - attributeData.CreateDiagnostic( + attributeData.CreateDiagnosticInfo( GeneratorDiagnostics.ConfigurationValueNotSupported, unsupportedValue, configurationName)); @@ -104,7 +104,7 @@ public void ReportMarshallingNotSupported( if (info.IsManagedReturnPosition) { _diagnostics.Add( - diagnosticLocation.CreateDiagnostic( + diagnosticLocation.CreateDiagnosticInfo( GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails, diagnosticProperties, notSupportedDetails!, @@ -113,7 +113,7 @@ public void ReportMarshallingNotSupported( else { _diagnostics.Add( - diagnosticLocation.CreateDiagnostic( + diagnosticLocation.CreateDiagnosticInfo( GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails, diagnosticProperties, notSupportedDetails!, @@ -128,7 +128,7 @@ public void ReportMarshallingNotSupported( if (info.IsManagedReturnPosition) { _diagnostics.Add( - diagnosticLocation.CreateDiagnostic( + diagnosticLocation.CreateDiagnosticInfo( GeneratorDiagnostics.ReturnConfigurationNotSupported, diagnosticProperties, nameof(System.Runtime.InteropServices.MarshalAsAttribute), @@ -137,7 +137,7 @@ public void ReportMarshallingNotSupported( else { _diagnostics.Add( - diagnosticLocation.CreateDiagnostic( + diagnosticLocation.CreateDiagnosticInfo( GeneratorDiagnostics.ParameterConfigurationNotSupported, diagnosticProperties, nameof(System.Runtime.InteropServices.MarshalAsAttribute), @@ -150,7 +150,7 @@ public void ReportMarshallingNotSupported( if (info.IsManagedReturnPosition) { _diagnostics.Add( - diagnosticLocation.CreateDiagnostic( + diagnosticLocation.CreateDiagnosticInfo( GeneratorDiagnostics.ReturnTypeNotSupported, diagnosticProperties, info.ManagedType.DiagnosticFormattedName, @@ -159,7 +159,7 @@ public void ReportMarshallingNotSupported( else { _diagnostics.Add( - diagnosticLocation.CreateDiagnostic( + diagnosticLocation.CreateDiagnosticInfo( GeneratorDiagnostics.ParameterTypeNotSupported, diagnosticProperties, info.ManagedType.DiagnosticFormattedName, diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs index 5f04c978a0289a..f89ab70d4535ee 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSExportGenerator.cs @@ -25,7 +25,7 @@ internal sealed record IncrementalStubGenerationContext( MethodSignatureDiagnosticLocations DiagnosticLocation, JSExportData JSExportData, MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version TargetFrameworkVersion, JSGeneratorOptions)> GeneratorFactoryKey, - SequenceEqualImmutableArray Diagnostics); + SequenceEqualImmutableArray Diagnostics); public static class StepNames { @@ -69,13 +69,13 @@ public void Initialize(IncrementalGeneratorInitializationContext context) if (data.Right.IsEmpty // no attributed methods || data.Left.Compilation.Options is CSharpCompilationOptions { AllowUnsafe: true }) // Unsafe code enabled { - return ImmutableArray.Empty; + return ImmutableArray.Empty; } - return ImmutableArray.Create(Diagnostic.Create(GeneratorDiagnostics.JSExportRequiresAllowUnsafeBlocks, null)); + return ImmutableArray.Create(DiagnosticInfo.Create(GeneratorDiagnostics.JSExportRequiresAllowUnsafeBlocks, null)); })); - IncrementalValuesProvider<(MemberDeclarationSyntax, StatementSyntax, AttributeListSyntax, ImmutableArray)> generateSingleStub = methodsToGenerate + IncrementalValuesProvider<(MemberDeclarationSyntax, StatementSyntax, AttributeListSyntax, ImmutableArray)> generateSingleStub = methodsToGenerate .Combine(stubEnvironment) .Combine(stubOptions) .Select(static (data, ct) => new @@ -214,7 +214,7 @@ private static IncrementalStubGenerationContext CalculateStubInformation( new MethodSignatureDiagnosticLocations(originalSyntax), jsExportData, CreateGeneratorFactory(environment, options), - new SequenceEqualImmutableArray(generatorDiagnostics.Diagnostics.ToImmutableArray())); + new SequenceEqualImmutableArray(generatorDiagnostics.Diagnostics.ToImmutableArray())); } private static MarshallingGeneratorFactoryKey<(TargetFramework, Version, JSGeneratorOptions)> CreateGeneratorFactory(StubEnvironment env, JSGeneratorOptions options) @@ -286,7 +286,7 @@ private static NamespaceDeclarationSyntax GenerateRegSource( return ns; } - private static (MemberDeclarationSyntax, StatementSyntax, AttributeListSyntax, ImmutableArray) GenerateSource( + private static (MemberDeclarationSyntax, StatementSyntax, AttributeListSyntax, ImmutableArray) GenerateSource( IncrementalStubGenerationContext incrementalContext) { var diagnostics = new GeneratorDiagnostics(); diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs index f4519ac0039d95..32214ca1b7aa25 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/gen/JSImportGenerator/JSImportGenerator.cs @@ -25,7 +25,7 @@ internal sealed record IncrementalStubGenerationContext( MethodSignatureDiagnosticLocations DiagnosticLocation, JSImportData JSImportData, MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version TargetFrameworkVersion, JSGeneratorOptions)> GeneratorFactoryKey, - SequenceEqualImmutableArray Diagnostics); + SequenceEqualImmutableArray Diagnostics); public static class StepNames { @@ -69,13 +69,13 @@ public void Initialize(IncrementalGeneratorInitializationContext context) if (data.Right.IsEmpty // no attributed methods || data.Left.Compilation.Options is CSharpCompilationOptions { AllowUnsafe: true }) // Unsafe code enabled { - return ImmutableArray.Empty; + return ImmutableArray.Empty; } - return ImmutableArray.Create(Diagnostic.Create(GeneratorDiagnostics.JSImportRequiresAllowUnsafeBlocks, null)); + return ImmutableArray.Create(DiagnosticInfo.Create(GeneratorDiagnostics.JSImportRequiresAllowUnsafeBlocks, null)); })); - IncrementalValuesProvider<(MemberDeclarationSyntax, ImmutableArray)> generateSingleStub = methodsToGenerate + IncrementalValuesProvider<(MemberDeclarationSyntax, ImmutableArray)> generateSingleStub = methodsToGenerate .Combine(stubEnvironment) .Combine(stubOptions) .Select(static (data, ct) => new @@ -201,7 +201,7 @@ private static IncrementalStubGenerationContext CalculateStubInformation( new MethodSignatureDiagnosticLocations(originalSyntax), jsImportData, CreateGeneratorFactory(environment, options), - new SequenceEqualImmutableArray(generatorDiagnostics.Diagnostics.ToImmutableArray())); + new SequenceEqualImmutableArray(generatorDiagnostics.Diagnostics.ToImmutableArray())); } private static MarshallingGeneratorFactoryKey<(TargetFramework, Version, JSGeneratorOptions)> CreateGeneratorFactory(StubEnvironment env, JSGeneratorOptions options) @@ -211,7 +211,7 @@ private static IncrementalStubGenerationContext CalculateStubInformation( return MarshallingGeneratorFactoryKey.Create((env.TargetFramework, env.TargetFrameworkVersion, options), jsGeneratorFactory); } - private static (MemberDeclarationSyntax, ImmutableArray) GenerateSource( + private static (MemberDeclarationSyntax, ImmutableArray) GenerateSource( IncrementalStubGenerationContext incrementalContext) { var diagnostics = new GeneratorDiagnostics(); diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSHostImplementation.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSHostImplementation.cs index b439586d213012..a333310a7d5b51 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSHostImplementation.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSHostImplementation.cs @@ -131,8 +131,9 @@ public static async Task ImportAsync(string moduleName, string moduleU { Task modulePromise = JavaScriptImports.DynamicImport(moduleName, moduleUrl); var wrappedTask = CancelationHelper(modulePromise, cancellationToken); - await Task.Yield();// this helps to finish the import before we bind the module in [JSImport] - return await wrappedTask.ConfigureAwait(true); + return await wrappedTask.ConfigureAwait( + ConfigureAwaitOptions.ContinueOnCapturedContext | + ConfigureAwaitOptions.ForceYielding); // this helps to finish the import before we bind the module in [JSImport] } public static async Task CancelationHelper(Task jsTask, CancellationToken cancellationToken) diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests.csproj b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests/System.Runtime.InteropServices.JavaScript.Legacy.Tests.csproj similarity index 98% rename from src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests.csproj rename to src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests/System.Runtime.InteropServices.JavaScript.Legacy.Tests.csproj index 1afaf6178ad2ee..e3d9f5609c7c62 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests.csproj +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests/System.Runtime.InteropServices.JavaScript.Legacy.Tests.csproj @@ -7,6 +7,7 @@ 0612 true $(DefineConstants);DISABLE_LEGACY_JS_INTEROP + WasmTestOnBrowser diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests/System/Runtime/InteropServices/JavaScript/HelperMarshal.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests/System/Runtime/InteropServices/JavaScript/HelperMarshal.cs index e69c2292416e1c..a3845136a03d69 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests/System/Runtime/InteropServices/JavaScript/HelperMarshal.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests/System/Runtime/InteropServices/JavaScript/HelperMarshal.cs @@ -7,7 +7,7 @@ namespace System.Runtime.InteropServices.JavaScript.Tests { public static class HelperMarshal { - internal const string INTEROP_CLASS = "[System.Runtime.InteropServices.JavaScript.Legacy.UnitTests]System.Runtime.InteropServices.JavaScript.Tests.HelperMarshal:"; + internal const string INTEROP_CLASS = "[System.Runtime.InteropServices.JavaScript.Legacy.Tests]System.Runtime.InteropServices.JavaScript.Tests.HelperMarshal:"; internal static int _i32Value; private static void InvokeI32(int a, int b) { diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs index 5b5a8cf9f82fcd..625ddcad9030eb 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests/System/Runtime/InteropServices/JavaScript/MarshalTests.cs @@ -611,6 +611,20 @@ public static void OnceAJSStringIsInternedItIsAlwaysUsedIfPossible() Assert.True(Object.ReferenceEquals(HelperMarshal._stringResource, HelperMarshal._stringResource2)); } + [Fact] + public static void ManuallyInternString() + { + HelperMarshal._stringResource = HelperMarshal._stringResource2 = null; + Utils.InvokeJS(@" + var sym = INTERNAL.stringToMonoStringIntern(""interned string 3""); + App.call_test_method (""InvokeString"", [ sym ], ""s""); + App.call_test_method (""InvokeString2"", [ sym ], ""s""); + "); + Assert.Equal("interned string 3", HelperMarshal._stringResource); + Assert.Equal(HelperMarshal._stringResource, HelperMarshal._stringResource2); + Assert.True(Object.ReferenceEquals(HelperMarshal._stringResource, HelperMarshal._stringResource2)); + } + [Fact] public static void LargeStringsAreNotAutomaticallyLocatedInInternTable() { @@ -619,7 +633,7 @@ public static void LargeStringsAreNotAutomaticallyLocatedInInternTable() var s = ""long interned string""; for (var i = 0; i < 1024; i++) s += String(i % 10); - var sym = INTERNAL.mono_intern_string(s); + var sym = INTERNAL.stringToMonoStringIntern(s); App.call_test_method (""InvokeString"", [ sym ], ""S""); App.call_test_method (""InvokeString2"", [ sym ], ""s""); "); @@ -633,7 +647,7 @@ public static void CanInternVeryManyStrings() HelperMarshal._stringResource = null; Utils.InvokeJS(@" for (var i = 0; i < 10240; i++) - INTERNAL.mono_intern_string('s' + i); + INTERNAL.stringToMonoStringIntern('s' + i); App.call_test_method (""InvokeString"", [ 's5000' ], ""S""); "); Assert.Equal("s5000", HelperMarshal._stringResource); @@ -658,7 +672,7 @@ public static void SymbolsAreMarshaledAsStrings() public static void InternedStringReturnValuesWork() { HelperMarshal._stringResource = HelperMarshal._stringResource2 = null; - var fqn = "[System.Runtime.InteropServices.JavaScript.Legacy.UnitTests]System.Runtime.InteropServices.JavaScript.Tests.HelperMarshal:StoreArgumentAndReturnLiteral"; + var fqn = "[System.Runtime.InteropServices.JavaScript.Legacy.Tests]System.Runtime.InteropServices.JavaScript.Tests.HelperMarshal:StoreArgumentAndReturnLiteral"; Utils.InvokeJS( $"var a = BINDING.bind_static_method('{fqn}')('test');\r\n" + $"var b = BINDING.bind_static_method('{fqn}')(a);\r\n" + diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests/timers.mjs b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests/timers.mjs index eceb916ef01e83..f0804845e72501 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests/timers.mjs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/tests/System.Runtime.InteropServices.JavaScript.Legacy.UnitTests/timers.mjs @@ -7,7 +7,7 @@ export function log(message) { } export function install() { - const measuredCallbackName = "mono_wasm_set_timeout_exec"; + const measuredCallbackName = "mono_wasm_schedule_timer_tick"; globalThis.registerCount = 0; globalThis.hitCount = 0; log("install") diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/GeneratedComInterfaceAttributeAnalyzer.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/GeneratedComInterfaceAttributeAnalyzer.cs index 11a628ddbd0a8c..9779d1e9287d4e 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/GeneratedComInterfaceAttributeAnalyzer.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Analyzers/GeneratedComInterfaceAttributeAnalyzer.cs @@ -41,7 +41,7 @@ public override void Initialize(AnalysisContext context) && GetAttribute(typeSymbol, TypeNames.InterfaceTypeAttribute, out AttributeData? comInterfaceAttribute) && !InterfaceTypeAttributeIsSupported(comInterfaceAttribute, out string unsupportedValue)) { - context.ReportDiagnostic(comInterfaceAttribute.CreateDiagnostic(AnalyzerDiagnostics.InterfaceTypeNotSupported, unsupportedValue)); + context.ReportDiagnostic(comInterfaceAttribute.CreateDiagnosticInfo(AnalyzerDiagnostics.InterfaceTypeNotSupported, unsupportedValue).ToDiagnostic()); } }, SymbolKind.NamedType); } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceContext.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceContext.cs index 54cfe877ec82e4..f8184a0b3fefcf 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceContext.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceContext.cs @@ -57,9 +57,9 @@ DiagnosticOr AddContext(ComInterfaceInfo iface) { // The base has failed generation at some point, so this interface cannot be generated var diagnostic = DiagnosticOr.From( - Diagnostic.Create( + DiagnosticInfo.Create( GeneratorDiagnostics.BaseInterfaceIsNotGenerated, - iface.DiagnosticLocation.AsLocation(), iface.ThisInterfaceKey, iface.BaseInterfaceKey)); + iface.DiagnosticLocation, iface.ThisInterfaceKey, iface.BaseInterfaceKey)); nameToContextCache[iface.ThisInterfaceKey] = diagnostic; return diagnostic; } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceInfo.cs index 31db875d638d48..9faa09c07e96c4 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceInfo.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComInterfaceInfo.cs @@ -9,6 +9,8 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.Interop; +using DiagnosticOrInterfaceInfo = Microsoft.Interop.DiagnosticOr<(Microsoft.Interop.ComInterfaceInfo InterfaceInfo, Microsoft.CodeAnalysis.INamedTypeSymbol Symbol) >; namespace Microsoft.Interop { @@ -23,9 +25,9 @@ internal sealed record ComInterfaceInfo( ContainingSyntaxContext TypeDefinitionContext, ContainingSyntax ContainingSyntax, Guid InterfaceId, - LocationInfo DiagnosticLocation) + Location DiagnosticLocation) { - public static DiagnosticOr<(ComInterfaceInfo InterfaceInfo, INamedTypeSymbol Symbol)> From(INamedTypeSymbol symbol, InterfaceDeclarationSyntax syntax, CancellationToken _) + public static DiagnosticOrInterfaceInfo From(INamedTypeSymbol symbol, InterfaceDeclarationSyntax syntax, CancellationToken _) { // Verify the method has no generic types or defined implementation // and is not marked static or sealed @@ -35,8 +37,8 @@ internal sealed record ComInterfaceInfo( // and is not marked static or sealed if (syntax.TypeParameterList is not null) { - return DiagnosticOr<(ComInterfaceInfo InterfaceInfo, INamedTypeSymbol Symbol)>.From( - Diagnostic.Create( + return DiagnosticOrInterfaceInfo.From( + DiagnosticInfo.Create( GeneratorDiagnostics.InvalidAttributedInterfaceGenericNotSupported, syntax.Identifier.GetLocation(), symbol.Name)); @@ -48,8 +50,8 @@ internal sealed record ComInterfaceInfo( { if (!typeDecl.Modifiers.Any(SyntaxKind.PartialKeyword)) { - return DiagnosticOr<(ComInterfaceInfo InterfaceInfo, INamedTypeSymbol Symbol)>.From( - Diagnostic.Create( + return DiagnosticOrInterfaceInfo.From( + DiagnosticInfo.Create( GeneratorDiagnostics.InvalidAttributedMethodContainingTypeMissingModifiers, syntax.Identifier.GetLocation(), symbol.Name, @@ -57,16 +59,16 @@ internal sealed record ComInterfaceInfo( } } - if (!TryGetGuid(symbol, syntax, out Guid? guid, out Diagnostic? guidDiagnostic)) - return DiagnosticOr<(ComInterfaceInfo InterfaceInfo, INamedTypeSymbol Symbol)>.From(guidDiagnostic); + if (!TryGetGuid(symbol, syntax, out Guid? guid, out DiagnosticInfo? guidDiagnostic)) + return DiagnosticOrInterfaceInfo.From(guidDiagnostic); - if (!TryGetBaseComInterface(symbol, syntax, out INamedTypeSymbol? baseSymbol, out Diagnostic? baseDiagnostic)) - return DiagnosticOr<(ComInterfaceInfo InterfaceInfo, INamedTypeSymbol Symbol)>.From(baseDiagnostic); + if (!TryGetBaseComInterface(symbol, syntax, out INamedTypeSymbol? baseSymbol, out DiagnosticInfo? baseDiagnostic)) + return DiagnosticOrInterfaceInfo.From(baseDiagnostic); - if (!StringMarshallingIsValid(symbol, syntax, baseSymbol, out Diagnostic? stringMarshallingDiagnostic)) - return DiagnosticOr<(ComInterfaceInfo InterfaceInfo, INamedTypeSymbol Symbol)>.From(stringMarshallingDiagnostic); + if (!StringMarshallingIsValid(symbol, syntax, baseSymbol, out DiagnosticInfo? stringMarshallingDiagnostic)) + return DiagnosticOrInterfaceInfo.From(stringMarshallingDiagnostic); - return DiagnosticOr<(ComInterfaceInfo InterfaceInfo, INamedTypeSymbol Symbol)>.From( + return DiagnosticOrInterfaceInfo.From( (new ComInterfaceInfo( ManagedTypeInfo.CreateTypeInfoForTypeSymbol(symbol), symbol.ToDisplayString(), @@ -75,18 +77,18 @@ internal sealed record ComInterfaceInfo( new ContainingSyntaxContext(syntax), new ContainingSyntax(syntax.Modifiers, syntax.Kind(), syntax.Identifier, syntax.TypeParameterList), guid ?? Guid.Empty, - LocationInfo.From(symbol)), + symbol.Locations[0]), symbol)); } - private static bool StringMarshallingIsValid(INamedTypeSymbol symbol, InterfaceDeclarationSyntax syntax, INamedTypeSymbol? baseSymbol, [NotNullWhen(false)] out Diagnostic? stringMarshallingDiagnostic) + private static bool StringMarshallingIsValid(INamedTypeSymbol symbol, InterfaceDeclarationSyntax syntax, INamedTypeSymbol? baseSymbol, [NotNullWhen(false)] out DiagnosticInfo? stringMarshallingDiagnostic) { var attrInfo = GeneratedComInterfaceData.From(GeneratedComInterfaceCompilationData.GetAttributeDataFromInterfaceSymbol(symbol)); if (attrInfo.IsUserDefined.HasFlag(InteropAttributeMember.StringMarshalling) || attrInfo.IsUserDefined.HasFlag(InteropAttributeMember.StringMarshallingCustomType)) { if (attrInfo.StringMarshalling is StringMarshalling.Custom && attrInfo.StringMarshallingCustomType is null) { - stringMarshallingDiagnostic = Diagnostic.Create( + stringMarshallingDiagnostic = DiagnosticInfo.Create( GeneratorDiagnostics.InvalidStringMarshallingConfigurationOnInterface, syntax.Identifier.GetLocation(), symbol.ToDisplayString(), @@ -95,7 +97,7 @@ private static bool StringMarshallingIsValid(INamedTypeSymbol symbol, InterfaceD } if (attrInfo.StringMarshalling is not StringMarshalling.Custom && attrInfo.StringMarshallingCustomType is not null) { - stringMarshallingDiagnostic = Diagnostic.Create( + stringMarshallingDiagnostic = DiagnosticInfo.Create( GeneratorDiagnostics.InvalidStringMarshallingConfigurationOnInterface, syntax.Identifier.GetLocation(), symbol.ToDisplayString(), @@ -110,7 +112,7 @@ private static bool StringMarshallingIsValid(INamedTypeSymbol symbol, InterfaceD if ((baseAttrInfo.IsUserDefined.HasFlag(InteropAttributeMember.StringMarshalling) || baseAttrInfo.IsUserDefined.HasFlag(InteropAttributeMember.StringMarshallingCustomType)) && baseAttrInfo != attrInfo) { - stringMarshallingDiagnostic = Diagnostic.Create( + stringMarshallingDiagnostic = DiagnosticInfo.Create( GeneratorDiagnostics.InvalidStringMarshallingMismatchBetweenBaseAndDerived, syntax.Identifier.GetLocation(), symbol.ToDisplayString(), @@ -125,7 +127,7 @@ private static bool StringMarshallingIsValid(INamedTypeSymbol symbol, InterfaceD /// /// Returns true if there is 0 or 1 base Com interfaces (i.e. the inheritance is valid), and returns false when there are 2 or more base Com interfaces and sets . /// - private static bool TryGetBaseComInterface(INamedTypeSymbol comIface, InterfaceDeclarationSyntax syntax, out INamedTypeSymbol? baseComIface, [NotNullWhen(false)] out Diagnostic? diagnostic) + private static bool TryGetBaseComInterface(INamedTypeSymbol comIface, InterfaceDeclarationSyntax syntax, out INamedTypeSymbol? baseComIface, [NotNullWhen(false)] out DiagnosticInfo? diagnostic) { baseComIface = null; foreach (var implemented in comIface.Interfaces) @@ -136,7 +138,7 @@ private static bool TryGetBaseComInterface(INamedTypeSymbol comIface, InterfaceD { if (baseComIface is not null) { - diagnostic = Diagnostic.Create( + diagnostic = DiagnosticInfo.Create( GeneratorDiagnostics.MultipleComInterfaceBaseTypes, syntax.Identifier.GetLocation(), comIface.ToDisplayString()); @@ -153,7 +155,7 @@ private static bool TryGetBaseComInterface(INamedTypeSymbol comIface, InterfaceD /// /// Returns true and sets if the guid is present. Returns false and sets diagnostic if the guid is not present or is invalid. /// - private static bool TryGetGuid(INamedTypeSymbol interfaceSymbol, InterfaceDeclarationSyntax syntax, [NotNullWhen(true)] out Guid? guid, [NotNullWhen(false)] out Diagnostic? diagnostic) + private static bool TryGetGuid(INamedTypeSymbol interfaceSymbol, InterfaceDeclarationSyntax syntax, [NotNullWhen(true)] out Guid? guid, [NotNullWhen(false)] out DiagnosticInfo? diagnostic) { guid = null; AttributeData? guidAttr = null; @@ -178,7 +180,7 @@ private static bool TryGetGuid(INamedTypeSymbol interfaceSymbol, InterfaceDeclar // Assume interfaceType is IUnknown for now if (guid is null) { - diagnostic = Diagnostic.Create( + diagnostic = DiagnosticInfo.Create( GeneratorDiagnostics.InvalidAttributedInterfaceMissingGuidAttribute, syntax.Identifier.GetLocation(), interfaceSymbol.ToDisplayString()); diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodInfo.cs index e11057fac7f787..c80290ffb0904b 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodInfo.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/ComMethodInfo.cs @@ -36,7 +36,7 @@ internal sealed record ComMethodInfo( return methods.ToImmutable().ToSequenceEqual(); } - private static Diagnostic? GetDiagnosticIfInvalidMethodForGeneration(MethodDeclarationSyntax comMethodDeclaringSyntax, IMethodSymbol method) + private static DiagnosticInfo? GetDiagnosticIfInvalidMethodForGeneration(MethodDeclarationSyntax comMethodDeclaringSyntax, IMethodSymbol method) { // Verify the method has no generic types or defined implementation // and is not marked static or sealed @@ -44,13 +44,13 @@ internal sealed record ComMethodInfo( || comMethodDeclaringSyntax.Body is not null || comMethodDeclaringSyntax.Modifiers.Any(SyntaxKind.SealedKeyword)) { - return Diagnostic.Create(GeneratorDiagnostics.InvalidAttributedMethodSignature, comMethodDeclaringSyntax.Identifier.GetLocation(), method.Name); + return DiagnosticInfo.Create(GeneratorDiagnostics.InvalidAttributedMethodSignature, comMethodDeclaringSyntax.Identifier.GetLocation(), method.Name); } // Verify the method does not have a ref return if (method.ReturnsByRef || method.ReturnsByRefReadonly) { - return Diagnostic.Create(GeneratorDiagnostics.ReturnConfigurationNotSupported, comMethodDeclaringSyntax.Identifier.GetLocation(), "ref return", method.ToDisplayString()); + return DiagnosticInfo.Create(GeneratorDiagnostics.ReturnConfigurationNotSupported, comMethodDeclaringSyntax.Identifier.GetLocation(), "ref return", method.ToDisplayString()); } return null; @@ -70,8 +70,8 @@ private static bool IsComMethodCandidate(ISymbol member) // [GeneratedComInterface] attribute. // This restriction not only makes finding the syntax for a given method cheaper, // but it also enables us to ensure that we can determine vtable method order easily. - Location interfaceLocation = ifaceContext.Declaration.GetLocation(); - Location? methodLocationInAttributedInterfaceDeclaration = null; + CodeAnalysis.Location interfaceLocation = ifaceContext.Declaration.GetLocation(); + CodeAnalysis.Location? methodLocationInAttributedInterfaceDeclaration = null; foreach (var methodLocation in method.Locations) { if (methodLocation.SourceTree == interfaceLocation.SourceTree @@ -84,7 +84,7 @@ private static bool IsComMethodCandidate(ISymbol member) if (methodLocationInAttributedInterfaceDeclaration is null) { - return DiagnosticOr<(ComMethodInfo, IMethodSymbol)>.From(Diagnostic.Create(GeneratorDiagnostics.MethodNotDeclaredInAttributedInterface, method.Locations.FirstOrDefault(), method.ToDisplayString())); + return DiagnosticOr<(ComMethodInfo, IMethodSymbol)>.From(DiagnosticInfo.Create(GeneratorDiagnostics.MethodNotDeclaredInAttributedInterface, method.Locations.FirstOrDefault(), method.ToDisplayString())); } @@ -102,7 +102,7 @@ private static bool IsComMethodCandidate(ISymbol member) } if (comMethodDeclaringSyntax is null) { - return DiagnosticOr<(ComMethodInfo, IMethodSymbol)>.From(Diagnostic.Create(GeneratorDiagnostics.CannotAnalyzeMethodPattern, method.Locations.FirstOrDefault(), method.ToDisplayString())); + return DiagnosticOr<(ComMethodInfo, IMethodSymbol)>.From(DiagnosticInfo.Create(GeneratorDiagnostics.CannotAnalyzeMethodPattern, method.Locations.FirstOrDefault(), method.ToDisplayString())); } var diag = GetDiagnosticIfInvalidMethodForGeneration(comMethodDeclaringSyntax, method); diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Comparers.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Comparers.cs index 3d710b6290e860..4f59d919804bc1 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Comparers.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/Comparers.cs @@ -15,7 +15,7 @@ internal static class Comparers /// /// Comparer for an individual generated stub source as a syntax tree and the generated diagnostics for the stub. /// - public static readonly IEqualityComparer<(MemberDeclarationSyntax Syntax, ImmutableArray Diagnostics)> GeneratedSyntax = new CustomValueTupleElementComparer>(SyntaxEquivalentComparer.Instance, new ImmutableArraySequenceEqualComparer(EqualityComparer.Default)); + public static readonly IEqualityComparer<(MemberDeclarationSyntax Syntax, ImmutableArray Diagnostics)> GeneratedSyntax = new CustomValueTupleElementComparer>(SyntaxEquivalentComparer.Instance, new ImmutableArraySequenceEqualComparer(EqualityComparer.Default)); } /// diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratedStubCodeContext.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratedStubCodeContext.cs index 6f0966ed776505..6f11382a5b4e4d 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratedStubCodeContext.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratedStubCodeContext.cs @@ -10,5 +10,5 @@ internal sealed record GeneratedStubCodeContext( ManagedTypeInfo OriginalDefiningType, ContainingSyntaxContext ContainingSyntaxContext, SyntaxEquivalentNode Stub, - SequenceEqualImmutableArray Diagnostics) : GeneratedMethodContextBase(OriginalDefiningType, Diagnostics); + SequenceEqualImmutableArray Diagnostics) : GeneratedMethodContextBase(OriginalDefiningType, Diagnostics); } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs index 2c47e3f5daacfc..f02a6c209963bf 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/GeneratorDiagnostics.cs @@ -29,6 +29,7 @@ public class Ids private const string Category = "ComInterfaceGenerator"; + /// public static readonly DiagnosticDescriptor InvalidAttributedMethodSignature = new DiagnosticDescriptor( Ids.InvalidLibraryImportAttributeUsage, @@ -39,6 +40,7 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.InvalidAttributedMethodDescription))); + /// public static readonly DiagnosticDescriptor InvalidAttributedMethodContainingTypeMissingModifiers = new DiagnosticDescriptor( Ids.InvalidLibraryImportAttributeUsage, @@ -49,6 +51,7 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.InvalidAttributedMethodDescription))); + /// public static readonly DiagnosticDescriptor InvalidAttributedMethodContainingTypeMissingUnmanagedObjectUnwrapperAttribute = new DiagnosticDescriptor( Ids.InvalidLibraryImportAttributeUsage, @@ -59,6 +62,7 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.InvalidAttributedMethodDescription))); + /// public static readonly DiagnosticDescriptor InvalidStringMarshallingMismatchBetweenBaseAndDerived = new DiagnosticDescriptor( Ids.InvalidGeneratedComInterfaceAttributeUsage, @@ -69,6 +73,7 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.GeneratedComInterfaceStringMarshallingMustMatchBase))); + /// public static readonly DiagnosticDescriptor InvalidStringMarshallingConfigurationOnMethod = new DiagnosticDescriptor( Ids.InvalidLibraryImportAttributeUsage, @@ -79,6 +84,7 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.InvalidStringMarshallingConfigurationDescription))); + /// public static readonly DiagnosticDescriptor InvalidStringMarshallingConfigurationOnInterface = new DiagnosticDescriptor( Ids.InvalidGeneratedComInterfaceAttributeUsage, @@ -89,6 +95,7 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.InvalidStringMarshallingConfigurationDescription))); + /// public static readonly DiagnosticDescriptor InvalidExceptionMarshallingConfiguration = new DiagnosticDescriptor( Ids.InvalidLibraryImportAttributeUsage, @@ -99,16 +106,18 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.InvalidExceptionMarshallingConfigurationDescription))); + /// public static readonly DiagnosticDescriptor ParameterTypeNotSupported = new DiagnosticDescriptor( Ids.TypeNotSupported, GetResourceString(nameof(SR.TypeNotSupportedTitle)), - GetResourceString(nameof(SR.TypeNotSupportedMessageParameter)), + GetResourceString(nameof(SR.InvalidExceptionMarshallingConfigurationMessage)), Category, DiagnosticSeverity.Error, isEnabledByDefault: true, description: GetResourceString(nameof(SR.TypeNotSupportedDescription))); + /// public static readonly DiagnosticDescriptor ReturnTypeNotSupported = new DiagnosticDescriptor( Ids.TypeNotSupported, @@ -119,6 +128,7 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.TypeNotSupportedDescription))); + /// public static readonly DiagnosticDescriptor ParameterTypeNotSupportedWithDetails = new DiagnosticDescriptor( Ids.TypeNotSupported, @@ -129,6 +139,7 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.TypeNotSupportedDescription))); + /// public static readonly DiagnosticDescriptor ReturnTypeNotSupportedWithDetails = new DiagnosticDescriptor( Ids.TypeNotSupported, @@ -139,6 +150,7 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.TypeNotSupportedDescription))); + /// public static readonly DiagnosticDescriptor ParameterConfigurationNotSupported = new DiagnosticDescriptor( Ids.ConfigurationNotSupported, @@ -149,6 +161,7 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.ConfigurationNotSupportedDescription))); + /// public static readonly DiagnosticDescriptor ReturnConfigurationNotSupported = new DiagnosticDescriptor( Ids.ConfigurationNotSupported, @@ -159,6 +172,7 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.ConfigurationNotSupportedDescription))); + /// public static readonly DiagnosticDescriptor ConfigurationNotSupported = new DiagnosticDescriptor( Ids.ConfigurationNotSupported, @@ -169,6 +183,7 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.ConfigurationNotSupportedDescription))); + /// public static readonly DiagnosticDescriptor ConfigurationValueNotSupported = new DiagnosticDescriptor( Ids.ConfigurationNotSupported, @@ -179,6 +194,7 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.ConfigurationNotSupportedDescription))); + /// public static readonly DiagnosticDescriptor MarshallingAttributeConfigurationNotSupported = new DiagnosticDescriptor( Ids.ConfigurationNotSupported, @@ -189,6 +205,7 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.ConfigurationNotSupportedDescription))); + /// public static readonly DiagnosticDescriptor MethodNotDeclaredInAttributedInterface = new DiagnosticDescriptor( Ids.MethodNotDeclaredInAttributedInterface, @@ -199,6 +216,7 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.MethodNotDeclaredInAttributedInterfaceDescription))); + /// public static readonly DiagnosticDescriptor InvalidAttributedInterfaceMissingGuidAttribute = new DiagnosticDescriptor( Ids.InvalidGeneratedComInterfaceAttributeUsage, @@ -209,6 +227,7 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.InvalidGeneratedComInterfaceAttributeUsageDescription))); + /// public static readonly DiagnosticDescriptor InvalidAttributedInterfaceGenericNotSupported = new DiagnosticDescriptor( Ids.InvalidGeneratedComInterfaceAttributeUsage, @@ -219,6 +238,7 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.InvalidGeneratedComInterfaceAttributeUsageDescription))); + /// public static readonly DiagnosticDescriptor MultipleComInterfaceBaseTypes = new DiagnosticDescriptor( Ids.MultipleComInterfaceBaseTypes, @@ -229,6 +249,7 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.MultipleComInterfaceBaseTypesDescription))); + /// public static readonly DiagnosticDescriptor CannotAnalyzeMethodPattern = new DiagnosticDescriptor( Ids.AnalysisFailed, @@ -239,6 +260,7 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.AnalysisFailedDescription))); + /// public static readonly DiagnosticDescriptor CannotAnalyzeInterfacePattern = new DiagnosticDescriptor( Ids.AnalysisFailed, @@ -249,6 +271,7 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.AnalysisFailedDescription))); + /// public static readonly DiagnosticDescriptor BaseInterfaceIsNotGenerated = new DiagnosticDescriptor( Ids.BaseInterfaceFailedGeneration, @@ -259,9 +282,9 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.BaseInterfaceCannotBeGeneratedDescription))); - private readonly List _diagnostics = new List(); + private readonly List _diagnostics = new List(); - public IEnumerable Diagnostics => _diagnostics; + public IEnumerable Diagnostics => _diagnostics; /// @@ -276,7 +299,7 @@ public void ReportInvalidStringMarshallingConfiguration( string detailsMessage) { _diagnostics.Add( - attributeData.CreateDiagnostic( + attributeData.CreateDiagnosticInfo( GeneratorDiagnostics.InvalidStringMarshallingConfigurationOnMethod, methodName, detailsMessage)); @@ -294,7 +317,7 @@ public void ReportInvalidExceptionMarshallingConfiguration( string detailsMessage) { _diagnostics.Add( - attributeData.CreateDiagnostic( + attributeData.CreateDiagnosticInfo( GeneratorDiagnostics.InvalidExceptionMarshallingConfiguration, methodName, detailsMessage)); @@ -314,14 +337,14 @@ public void ReportConfigurationNotSupported( if (unsupportedValue == null) { _diagnostics.Add( - attributeData.CreateDiagnostic( + attributeData.CreateDiagnosticInfo( GeneratorDiagnostics.ConfigurationNotSupported, configurationName)); } else { _diagnostics.Add( - attributeData.CreateDiagnostic( + attributeData.CreateDiagnosticInfo( GeneratorDiagnostics.ConfigurationValueNotSupported, unsupportedValue, configurationName)); @@ -339,7 +362,7 @@ public void ReportMarshallingNotSupported( TypePositionInfo info, string? notSupportedDetails) { - Location diagnosticLocation = Location.None; + CodeAnalysis.Location diagnosticLocation = CodeAnalysis.Location.None; string elementName = string.Empty; if (info.IsManagedReturnPosition) @@ -360,7 +383,7 @@ public void ReportMarshallingNotSupported( if (info.IsManagedReturnPosition) { _diagnostics.Add( - diagnosticLocation.CreateDiagnostic( + diagnosticLocation.CreateDiagnosticInfo( GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails, notSupportedDetails!, elementName)); @@ -368,7 +391,7 @@ public void ReportMarshallingNotSupported( else { _diagnostics.Add( - diagnosticLocation.CreateDiagnostic( + diagnosticLocation.CreateDiagnosticInfo( GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails, notSupportedDetails!, elementName)); @@ -382,7 +405,7 @@ public void ReportMarshallingNotSupported( if (info.IsManagedReturnPosition) { _diagnostics.Add( - diagnosticLocation.CreateDiagnostic( + diagnosticLocation.CreateDiagnosticInfo( GeneratorDiagnostics.ReturnConfigurationNotSupported, nameof(System.Runtime.InteropServices.MarshalAsAttribute), elementName)); @@ -390,7 +413,7 @@ public void ReportMarshallingNotSupported( else { _diagnostics.Add( - diagnosticLocation.CreateDiagnostic( + diagnosticLocation.CreateDiagnosticInfo( GeneratorDiagnostics.ParameterConfigurationNotSupported, nameof(System.Runtime.InteropServices.MarshalAsAttribute), elementName)); @@ -402,7 +425,7 @@ public void ReportMarshallingNotSupported( if (info.IsManagedReturnPosition) { _diagnostics.Add( - diagnosticLocation.CreateDiagnostic( + diagnosticLocation.CreateDiagnosticInfo( GeneratorDiagnostics.ReturnTypeNotSupported, info.ManagedType.DiagnosticFormattedName, elementName)); @@ -410,7 +433,7 @@ public void ReportMarshallingNotSupported( else { _diagnostics.Add( - diagnosticLocation.CreateDiagnostic( + diagnosticLocation.CreateDiagnosticInfo( GeneratorDiagnostics.ParameterTypeNotSupported, info.ManagedType.DiagnosticFormattedName, elementName)); @@ -424,7 +447,7 @@ public void ReportInvalidMarshallingAttributeInfo( params string[] reasonArgs) { _diagnostics.Add( - attributeData.CreateDiagnostic( + attributeData.CreateDiagnosticInfo( GeneratorDiagnostics.MarshallingAttributeConfigurationNotSupported, new LocalizableResourceString(reasonResourceName, SR.ResourceManager, typeof(FxResources.Microsoft.Interop.ComInterfaceGenerator.SR), reasonArgs))); } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/IncrementalMethodStubGenerationContext.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/IncrementalMethodStubGenerationContext.cs index fae4de0e1167c5..711cd89a99b648 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/IncrementalMethodStubGenerationContext.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/IncrementalMethodStubGenerationContext.cs @@ -7,7 +7,7 @@ namespace Microsoft.Interop { - internal abstract record GeneratedMethodContextBase(ManagedTypeInfo OriginalDefiningType, SequenceEqualImmutableArray Diagnostics); + internal abstract record GeneratedMethodContextBase(ManagedTypeInfo OriginalDefiningType, SequenceEqualImmutableArray Diagnostics); internal sealed record IncrementalMethodStubGenerationContext( SignatureContext SignatureContext, @@ -21,6 +21,6 @@ internal sealed record IncrementalMethodStubGenerationContext( MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version TargetFrameworkVersion)> UnmanagedToManagedGeneratorFactory, ManagedTypeInfo TypeKeyOwner, ManagedTypeInfo DeclaringType, - SequenceEqualImmutableArray Diagnostics, + SequenceEqualImmutableArray Diagnostics, MarshallingInfo ManagedThisMarshallingInfo) : GeneratedMethodContextBase(DeclaringType, Diagnostics); } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/LocationInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/LocationInfo.cs deleted file mode 100644 index 982e1ca75bc6ab..00000000000000 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/LocationInfo.cs +++ /dev/null @@ -1,29 +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.CodeAnalysis; -using Microsoft.CodeAnalysis.Text; - -namespace Microsoft.Interop -{ - /// - /// Contains data required to reconstruct a without keeping any symbols or references to a - /// - internal sealed record LocationInfo( - LinePositionSpan LinePositionSpan, - string FilePath, - TextSpan TextSpan) - { - public Location AsLocation() => Location.Create(FilePath, TextSpan, LinePositionSpan); - - public static LocationInfo From(ISymbol symbol) - { - var location = symbol.Locations[0]; - var lineSpan = location.GetLineSpan().Span; - var filePath = location.SourceTree.FilePath; - var textSpan = location.SourceSpan; - - return new LocationInfo(lineSpan, filePath, textSpan); - } - } -} diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/SkippedStubContext.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/SkippedStubContext.cs index aa9ef047ba0490..6f4b474a914d2a 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/SkippedStubContext.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/SkippedStubContext.cs @@ -6,5 +6,5 @@ namespace Microsoft.Interop { - internal sealed record SkippedStubContext(ManagedTypeInfo OriginalDefiningType) : GeneratedMethodContextBase(OriginalDefiningType, new(ImmutableArray.Empty)); + internal sealed record SkippedStubContext(ManagedTypeInfo OriginalDefiningType) : GeneratedMethodContextBase(OriginalDefiningType, new(ImmutableArray.Empty)); } diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodPointerStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodPointerStubGenerator.cs index e813c8fb906e6e..f5a8a713db3d97 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodPointerStubGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VirtualMethodPointerStubGenerator.cs @@ -15,7 +15,7 @@ namespace Microsoft.Interop { internal static class VirtualMethodPointerStubGenerator { - public static (MethodDeclarationSyntax, ImmutableArray) GenerateManagedToNativeStub( + public static (MethodDeclarationSyntax, ImmutableArray) GenerateManagedToNativeStub( IncrementalMethodStubGenerationContext methodStub) { var diagnostics = new GeneratorDiagnostics(); @@ -65,7 +65,7 @@ private static MethodDeclarationSyntax PrintGeneratedSource( private const string ThisParameterIdentifier = "@this"; - public static (MethodDeclarationSyntax, ImmutableArray) GenerateNativeToManagedStub( + public static (MethodDeclarationSyntax, ImmutableArray) GenerateNativeToManagedStub( IncrementalMethodStubGenerationContext methodStub) { var diagnostics = new GeneratorDiagnostics(); diff --git a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs index 43600ca57e37e5..f674968c81f392 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/ComInterfaceGenerator/VtableIndexStubGenerator.cs @@ -75,7 +75,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .WithTrackingName(StepNames.CalculateStubInformation); // Generate the code for the managed-to-unmangaed stubs and the diagnostics from code-generation. - IncrementalValuesProvider<(MemberDeclarationSyntax, ImmutableArray)> generateManagedToNativeStub = generateStubInformation + IncrementalValuesProvider<(MemberDeclarationSyntax, ImmutableArray)> generateManagedToNativeStub = generateStubInformation .Where(data => data.VtableIndexData.Direction is MarshalDirection.ManagedToUnmanaged or MarshalDirection.Bidirectional) .Select( static (data, ct) => GenerateManagedToNativeStub(data) @@ -93,7 +93,7 @@ public void Initialize(IncrementalGeneratorInitializationContext context) .Where(data => data.VtableIndexData.Direction is MarshalDirection.UnmanagedToManaged or MarshalDirection.Bidirectional); // Generate the code for the unmanaged-to-managed stubs and the diagnostics from code-generation. - IncrementalValuesProvider<(MemberDeclarationSyntax, ImmutableArray)> generateNativeToManagedStub = nativeToManagedStubContexts + IncrementalValuesProvider<(MemberDeclarationSyntax, ImmutableArray)> generateNativeToManagedStub = nativeToManagedStubContexts .Select( static (data, ct) => GenerateNativeToManagedStub(data) ) @@ -311,7 +311,7 @@ private static IncrementalMethodStubGenerationContext CalculateStubInformation(M VtableIndexStubGeneratorHelpers.CreateGeneratorFactory(environment, MarshalDirection.UnmanagedToManaged), interfaceType, interfaceType, - new SequenceEqualImmutableArray(generatorDiagnostics.Diagnostics.ToImmutableArray()), + new SequenceEqualImmutableArray(generatorDiagnostics.Diagnostics.ToImmutableArray()), new ObjectUnwrapperInfo(unwrapperSyntax)); } @@ -356,7 +356,7 @@ private static MarshallingInfo CreateExceptionMarshallingInfo(AttributeData virt return NoMarshallingInfo.Instance; } - private static (MemberDeclarationSyntax, ImmutableArray) GenerateManagedToNativeStub( + private static (MemberDeclarationSyntax, ImmutableArray) GenerateManagedToNativeStub( IncrementalMethodStubGenerationContext methodStub) { var (stub, diagnostics) = VirtualMethodPointerStubGenerator.GenerateManagedToNativeStub(methodStub); @@ -369,7 +369,7 @@ private static (MemberDeclarationSyntax, ImmutableArray) GenerateMan methodStub.Diagnostics.Array.AddRange(diagnostics)); } - private static (MemberDeclarationSyntax, ImmutableArray) GenerateNativeToManagedStub( + private static (MemberDeclarationSyntax, ImmutableArray) GenerateNativeToManagedStub( IncrementalMethodStubGenerationContext methodStub) { var (stub, diagnostics) = VirtualMethodPointerStubGenerator.GenerateNativeToManagedStub(methodStub); diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs index 69bd46cbf5cec1..03a8141eb50a33 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/ConvertToLibraryImportAnalyzer.cs @@ -136,7 +136,7 @@ private static void AnalyzeSymbol(SymbolAnalysisContext context, INamedTypeSymbo properties.Add(ExactSpelling, dllImportData.ExactSpelling.ToString()); properties.Add(MayRequireAdditionalWork, mayRequireAdditionalWork.ToString()); - context.ReportDiagnostic(method.CreateDiagnostic(ConvertToLibraryImport, properties.ToImmutable(), method.Name)); + context.ReportDiagnostic(method.CreateDiagnosticInfo(ConvertToLibraryImport, properties.ToImmutable(), method.Name).ToDiagnostic()); } private static bool HasUnsupportedMarshalAsInfo(TypePositionInfo info) diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/CustomMarshallerAttributeFixer.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/CustomMarshallerAttributeFixer.cs index f3591046715427..cf78e8af6065ab 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/CustomMarshallerAttributeFixer.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/CustomMarshallerAttributeFixer.cs @@ -184,7 +184,7 @@ private static async Task AddMissingMembers(Document doc, SyntaxNode n // Get the managed type from the CustomMarshallerAttribute located at the provided location in source on the provided type. // As we only get fixable diagnostics for types that have valid non-null managed types in the CustomMarshallerAttribute applications, // we do not need to worry about the returned symbol being null. - private static ITypeSymbol GetManagedTypeInAttributeSyntax(Location locationInAttribute, INamedTypeSymbol attributedTypeSymbol) + private static ITypeSymbol GetManagedTypeInAttributeSyntax(CodeAnalysis.Location locationInAttribute, INamedTypeSymbol attributedTypeSymbol) => (ITypeSymbol)attributedTypeSymbol.GetAttributes().First(attr => attr.ApplicationSyntaxReference.SyntaxTree == locationInAttribute.SourceTree && attr.ApplicationSyntaxReference.Span.Contains(locationInAttribute.SourceSpan)).ConstructorArguments[0].Value!; diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/DiagnosticReporter.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/DiagnosticReporter.cs index 27a9dbebc5f78b..b128616d8f5340 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/DiagnosticReporter.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Analyzers/DiagnosticReporter.cs @@ -16,7 +16,7 @@ public DiagnosticReporter(Action reportDiagnostic) => new((descriptor, properties, args) => reportDiagnostic(location.CreateDiagnostic(descriptor, properties, args))); + public static DiagnosticReporter CreateForLocation(CodeAnalysis.Location location, Action reportDiagnostic) => new((descriptor, properties, args) => reportDiagnostic(location.CreateDiagnosticInfo(descriptor, properties, args).ToDiagnostic())); public void CreateAndReportDiagnostic(DiagnosticDescriptor descriptor, params object[] messageArgs) => _diagnosticFactory(descriptor, ImmutableDictionary.Empty, messageArgs); diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Comparers.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Comparers.cs index 3d710b6290e860..87a565111f6b1e 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Comparers.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/Comparers.cs @@ -15,8 +15,8 @@ internal static class Comparers /// /// Comparer for an individual generated stub source as a syntax tree and the generated diagnostics for the stub. /// - public static readonly IEqualityComparer<(MemberDeclarationSyntax Syntax, ImmutableArray Diagnostics)> GeneratedSyntax = new CustomValueTupleElementComparer>(SyntaxEquivalentComparer.Instance, new ImmutableArraySequenceEqualComparer(EqualityComparer.Default)); - } + public static readonly IEqualityComparer<(MemberDeclarationSyntax Syntax, ImmutableArray Diagnostics)> GeneratedSyntax = new CustomValueTupleElementComparer>(SyntaxEquivalentComparer.Instance, new ImmutableArraySequenceEqualComparer(EqualityComparer.Default)); + } /// /// Generic comparer to compare two instances element by element. diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/GeneratorDiagnostics.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/GeneratorDiagnostics.cs index 920be3c33de52a..10546870f1eec8 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/GeneratorDiagnostics.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/GeneratorDiagnostics.cs @@ -169,9 +169,9 @@ public class Ids isEnabledByDefault: true, description: GetResourceString(nameof(SR.RequiresAllowUnsafeBlocksDescription))); - private readonly List _diagnostics = new List(); + private readonly List _diagnostics = new List(); - public IEnumerable Diagnostics => _diagnostics; + public IEnumerable Diagnostics => _diagnostics; /// /// Report diagnostic for invalid configuration for string marshalling. @@ -185,7 +185,7 @@ public void ReportInvalidStringMarshallingConfiguration( string detailsMessage) { _diagnostics.Add( - attributeData.CreateDiagnostic( + attributeData.CreateDiagnosticInfo( GeneratorDiagnostics.InvalidStringMarshallingConfiguration, methodName, detailsMessage)); @@ -205,14 +205,14 @@ public void ReportConfigurationNotSupported( if (unsupportedValue == null) { _diagnostics.Add( - attributeData.CreateDiagnostic( + attributeData.CreateDiagnosticInfo( GeneratorDiagnostics.ConfigurationNotSupported, configurationName)); } else { _diagnostics.Add( - attributeData.CreateDiagnostic( + attributeData.CreateDiagnosticInfo( GeneratorDiagnostics.ConfigurationValueNotSupported, unsupportedValue, configurationName)); @@ -231,7 +231,7 @@ public void ReportMarshallingNotSupported( string? notSupportedDetails, ImmutableDictionary diagnosticProperties) { - Location diagnosticLocation = Location.None; + CodeAnalysis.Location diagnosticLocation = CodeAnalysis.Location.None; string elementName = string.Empty; if (info.IsManagedReturnPosition) @@ -252,7 +252,7 @@ public void ReportMarshallingNotSupported( if (info.IsManagedReturnPosition) { _diagnostics.Add( - diagnosticLocation.CreateDiagnostic( + diagnosticLocation.CreateDiagnosticInfo( GeneratorDiagnostics.ReturnTypeNotSupportedWithDetails, diagnosticProperties, notSupportedDetails!, @@ -261,7 +261,7 @@ public void ReportMarshallingNotSupported( else { _diagnostics.Add( - diagnosticLocation.CreateDiagnostic( + diagnosticLocation.CreateDiagnosticInfo( GeneratorDiagnostics.ParameterTypeNotSupportedWithDetails, diagnosticProperties, notSupportedDetails!, @@ -276,7 +276,7 @@ public void ReportMarshallingNotSupported( if (info.IsManagedReturnPosition) { _diagnostics.Add( - diagnosticLocation.CreateDiagnostic( + diagnosticLocation.CreateDiagnosticInfo( GeneratorDiagnostics.ReturnConfigurationNotSupported, diagnosticProperties, nameof(System.Runtime.InteropServices.MarshalAsAttribute), @@ -285,7 +285,7 @@ public void ReportMarshallingNotSupported( else { _diagnostics.Add( - diagnosticLocation.CreateDiagnostic( + diagnosticLocation.CreateDiagnosticInfo( GeneratorDiagnostics.ParameterConfigurationNotSupported, diagnosticProperties, nameof(System.Runtime.InteropServices.MarshalAsAttribute), @@ -298,7 +298,7 @@ public void ReportMarshallingNotSupported( if (info.IsManagedReturnPosition) { _diagnostics.Add( - diagnosticLocation.CreateDiagnostic( + diagnosticLocation.CreateDiagnosticInfo( GeneratorDiagnostics.ReturnTypeNotSupported, diagnosticProperties, info.ManagedType.DiagnosticFormattedName, @@ -307,7 +307,7 @@ public void ReportMarshallingNotSupported( else { _diagnostics.Add( - diagnosticLocation.CreateDiagnostic( + diagnosticLocation.CreateDiagnosticInfo( GeneratorDiagnostics.ParameterTypeNotSupported, diagnosticProperties, info.ManagedType.DiagnosticFormattedName, @@ -322,7 +322,7 @@ public void ReportInvalidMarshallingAttributeInfo( params string[] reasonArgs) { _diagnostics.Add( - attributeData.CreateDiagnostic( + attributeData.CreateDiagnosticInfo( GeneratorDiagnostics.MarshallingAttributeConfigurationNotSupported, new LocalizableResourceString(reasonResourceName, SR.ResourceManager, typeof(FxResources.Microsoft.Interop.LibraryImportGenerator.SR), reasonArgs))); } @@ -336,7 +336,7 @@ public void ReportInvalidMarshallingAttributeInfo( public void ReportCannotForwardToDllImport(MethodSignatureDiagnosticLocations method, string name, string? value = null) { _diagnostics.Add( - Diagnostic.Create( + DiagnosticInfo.Create( CannotForwardToDllImport, method.FallbackLocation, value is null ? name : $"{name}={value}")); diff --git a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs index b0b14372adec30..8bc3457b08ff40 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/LibraryImportGenerator/LibraryImportGenerator.cs @@ -28,7 +28,7 @@ internal sealed record IncrementalStubGenerationContext( SequenceEqualImmutableArray ForwardedAttributes, LibraryImportData LibraryImportData, MarshallingGeneratorFactoryKey<(TargetFramework TargetFramework, Version Version, LibraryImportGeneratorOptions Options)> GeneratorFactoryKey, - SequenceEqualImmutableArray Diagnostics); + SequenceEqualImmutableArray Diagnostics); public static class StepNames { @@ -78,13 +78,13 @@ public void Initialize(IncrementalGeneratorInitializationContext context) || data.Left.Compilation.Options is CSharpCompilationOptions { AllowUnsafe: true } // Unsafe code enabled || data.Left.TargetFramework != TargetFramework.Net) // Non-.NET 5 scenarios use forwarders and don't need unsafe code { - return ImmutableArray.Empty; + return ImmutableArray.Empty; } - return ImmutableArray.Create(Diagnostic.Create(GeneratorDiagnostics.RequiresAllowUnsafeBlocks, null)); + return ImmutableArray.Create(DiagnosticInfo.Create(GeneratorDiagnostics.RequiresAllowUnsafeBlocks, null)); })); - IncrementalValuesProvider<(MemberDeclarationSyntax, ImmutableArray)> generateSingleStub = methodsToGenerate + IncrementalValuesProvider<(MemberDeclarationSyntax, ImmutableArray)> generateSingleStub = methodsToGenerate .Combine(stubEnvironment) .Combine(stubOptions) .Select(static (data, ct) => new @@ -303,11 +303,11 @@ private static IncrementalStubGenerationContext CalculateStubInformation( new SequenceEqualImmutableArray(additionalAttributes.ToImmutableArray(), SyntaxEquivalentComparer.Instance), LibraryImportData.From(libraryImportData), LibraryImportGeneratorHelpers.CreateGeneratorFactory(environment, options), - new SequenceEqualImmutableArray(generatorDiagnostics.Diagnostics.ToImmutableArray()) + new SequenceEqualImmutableArray(generatorDiagnostics.Diagnostics.ToImmutableArray()) ); } - private static (MemberDeclarationSyntax, ImmutableArray) GenerateSource( + private static (MemberDeclarationSyntax, ImmutableArray) GenerateSource( IncrementalStubGenerationContext pinvokeStub, LibraryImportGeneratorOptions options) { diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/DiagnosticInfo.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/DiagnosticInfo.cs new file mode 100644 index 00000000000000..91072e62795dbc --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/DiagnosticInfo.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.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using Microsoft.CodeAnalysis; + +namespace Microsoft.Interop +{ + public record DiagnosticInfo + { + public required DiagnosticDescriptor Descriptor { get; init; } + public required SequenceEqualImmutableArray MessageArgs { get; init; } + public required Location? Location { get; init; } + public required IEnumerable? AdditionalLocations { get; init; } + public required ValueEqualityImmutableDictionary? Properties { get; init; } + + public Diagnostic ToDiagnostic() => Diagnostic.Create( + Descriptor, + Location, + additionalLocations: AdditionalLocations, + properties: Properties?.Map, + messageArgs: MessageArgs.Array.ToArray()); + + public static DiagnosticInfo Create(DiagnosticDescriptor descriptor, CodeAnalysis.Location location, params object?[] messageArgs) + { + return new DiagnosticInfo() + { + Descriptor = descriptor, + Location = location, + AdditionalLocations = null, + Properties = null, + MessageArgs = messageArgs.Select(o => o?.ToString()).ToSequenceEqualImmutableArray() + }; + } + + public static DiagnosticInfo Create(DiagnosticDescriptor descriptor, CodeAnalysis.Location location, ImmutableDictionary? properties, params object?[] messageArgs) + { + return new DiagnosticInfo() + { + Descriptor = descriptor, + Location = location, + AdditionalLocations = null, + Properties = properties.ToValueEquals(), + MessageArgs = messageArgs.Select(o => o.ToString()).ToSequenceEqualImmutableArray() + }; + } + + public static DiagnosticInfo Create(DiagnosticDescriptor descriptor, CodeAnalysis.Location location, IEnumerable? additionalLocations, ImmutableDictionary? properties, params object?[] messageArgs) + { + return new DiagnosticInfo() + { + Descriptor = descriptor, + Location = location, + AdditionalLocations = additionalLocations, + Properties = properties.ToValueEquals(), + MessageArgs = messageArgs.Select(o => o.ToString()).ToSequenceEqualImmutableArray() + }; + } + } +} diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/DiagnosticOr.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/DiagnosticOr.cs index 0be31fa6277675..caa15d3a0d6664 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/DiagnosticOr.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/DiagnosticOr.cs @@ -32,15 +32,15 @@ public abstract record DiagnosticOr /// /// Throws if IsDiagnostic is false /// - public abstract Diagnostic Diagnostic { get; } + public abstract DiagnosticInfo Diagnostic { get; } private sealed record Diag : DiagnosticOr { - private readonly Diagnostic _diagnostic; - internal Diag(Diagnostic diagnostic) => _diagnostic = diagnostic; + private readonly DiagnosticInfo _diagnostic; + internal Diag(DiagnosticInfo diagnostic) => _diagnostic = diagnostic; public override bool IsValue => false; public override T Value => throw new InvalidOperationException(); - public override Diagnostic Diagnostic => _diagnostic; + public override DiagnosticInfo Diagnostic => _diagnostic; } private sealed record Val : DiagnosticOr @@ -49,13 +49,13 @@ private sealed record Val : DiagnosticOr internal Val(T value) => _value = value; public override bool IsValue => true; public override T Value => _value; - public override Diagnostic Diagnostic => throw new InvalidOperationException(); + public override DiagnosticInfo Diagnostic => throw new InvalidOperationException(); } /// /// Create a Diagnostic variant /// - public static DiagnosticOr From(Diagnostic diagnostic) + public static DiagnosticOr From(DiagnosticInfo diagnostic) { Debug.Assert(diagnostic is not null); return new Diag(diagnostic); @@ -76,7 +76,7 @@ public static class DiagnosticOrTHelperExtensions /// /// Splits the elements of into a "values" provider and a "diagnositics" provider. /// - public static (IncrementalValuesProvider, IncrementalValuesProvider) Split(this IncrementalValuesProvider> provider) + public static (IncrementalValuesProvider, IncrementalValuesProvider) Split(this IncrementalValuesProvider> provider) { var values = provider.Where(x => x.IsValue).Select(static (x, ct) => x.Value); var diagnostics = provider.Where(x => x.IsDiagnostic).Select(static (x, ct) => x.Diagnostic); @@ -86,7 +86,7 @@ public static (IncrementalValuesProvider, IncrementalValuesProvider /// Splits the inner arrays of into values and diagnostics. /// - public static (IncrementalValuesProvider>, IncrementalValuesProvider) SplitArrays(this IncrementalValuesProvider>> provider) + public static (IncrementalValuesProvider>, IncrementalValuesProvider) SplitArrays(this IncrementalValuesProvider>> provider) { var values = provider.Select((arr, ct) => arr.Where(x => x.IsValue).Select((x, ct) => x.Value).ToSequenceEqualImmutableArray()); var diagnostics = provider.SelectMany((arr, ct) => arr.Where(x => x.IsDiagnostic).Select((x, ct) => x.Diagnostic)); @@ -96,7 +96,7 @@ public static (IncrementalValuesProvider>, Increm /// /// Splits the elements of into groups depending on whether Item1 is a value or a Diagnostic. /// - public static (IncrementalValuesProvider<(T, T2)>, IncrementalValuesProvider) Split(this IncrementalValuesProvider<(DiagnosticOr, T2)> provider) + public static (IncrementalValuesProvider<(T, T2)>, IncrementalValuesProvider) Split(this IncrementalValuesProvider<(DiagnosticOr, T2)> provider) { var values = provider.Where(x => x.Item1.IsValue).Select(static (x, ct) => (x.Item1.Value, x.Item2)); var diagnostics = provider.Where(x => !x.Item1.IsValue).Select(static (x, ct) => x.Item1.Diagnostic); diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs index 47c94836859485..e620875eae719f 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IGeneratorDiagnostics.cs @@ -1,13 +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; using System.Collections.Generic; using System.Collections.Immutable; -using System.Diagnostics; - using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp.Syntax; namespace Microsoft.Interop { @@ -90,7 +86,7 @@ public static Diagnostic CreateDiagnostic( return firstLocation is null ? Diagnostic.Create(descriptor, Location.None, properties: properties, args) : - Diagnostic.Create(descriptor, firstLocation, additionalLocations, properties, args); + Diagnostic.Create(descriptor, firstLocation, additionalLocations: additionalLocations, properties: properties, messageArgs: args); } public static Diagnostic CreateDiagnostic( @@ -116,6 +112,110 @@ public static Diagnostic CreateDiagnostic( properties: properties, messageArgs: args); } + + public static DiagnosticInfo CreateDiagnosticInfo( + this ISymbol symbol, + DiagnosticDescriptor descriptor, + params object[] args) + { + return symbol.Locations.CreateDiagnosticInfo(descriptor, args); + } + + public static DiagnosticInfo CreateDiagnosticInfo( + this ISymbol symbol, + DiagnosticDescriptor descriptor, + ImmutableDictionary properties, + params object[] args) + { + return symbol.Locations.CreateDiagnosticInfo(descriptor, properties, args); + } + + public static DiagnosticInfo CreateDiagnosticInfo( + this AttributeData attributeData, + DiagnosticDescriptor descriptor, + params object[] args) + { + SyntaxReference? syntaxReference = attributeData.ApplicationSyntaxReference; + Location location = syntaxReference is not null + ? syntaxReference.SyntaxTree.GetLocation(syntaxReference.Span) + : Location.None; + + return location.CreateDiagnosticInfo(descriptor, args); + } + + public static DiagnosticInfo CreateDiagnosticInfo( + this AttributeData attributeData, + DiagnosticDescriptor descriptor, + ImmutableDictionary properties, + params object[] args) + { + SyntaxReference? syntaxReference = attributeData.ApplicationSyntaxReference; + Location location = syntaxReference is not null + ? syntaxReference.SyntaxTree.GetLocation(syntaxReference.Span) + : Location.None; + + return location.CreateDiagnosticInfo(descriptor, properties, args); + } + + public static DiagnosticInfo CreateDiagnosticInfo( + this ImmutableArray locations, + DiagnosticDescriptor descriptor, + params object[] args) + { + return CreateDiagnosticInfo(locations, descriptor, properties: null, args); + } + + public static DiagnosticInfo CreateDiagnosticInfo( + this ImmutableArray locations, + DiagnosticDescriptor descriptor, + ImmutableDictionary properties, + params object[] args) + { + Location firstLocation = null; + List additionalLocations = null; + foreach (Location location in locations) + { + if (location.IsInSource) + { + if (firstLocation is null) + { + firstLocation = location; + } + else + { + (additionalLocations ??= new()).Add(location); + } + } + } + + return firstLocation is null ? + DiagnosticInfo.Create(descriptor, Location.None, properties: properties, args) : + DiagnosticInfo.Create(descriptor, firstLocation, additionalLocations: additionalLocations, properties: properties, messageArgs: args); + } + + public static DiagnosticInfo CreateDiagnosticInfo( + this Location location, + DiagnosticDescriptor descriptor, + params object[] args) + { + return DiagnosticInfo.Create( + descriptor, + location: location.IsInSource ? location : Location.None, + messageArgs: args); + } + + public static DiagnosticInfo CreateDiagnosticInfo( + this Location location, + DiagnosticDescriptor descriptor, + ImmutableDictionary properties, + params object[] args) + { + return DiagnosticInfo.Create( + descriptor, + location: location.IsInSource ? location : Location.None, + properties: properties, + messageArgs: args); + } } diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IncrementalGeneratorInitializationContextExtensions.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IncrementalGeneratorInitializationContextExtensions.cs index d0adc407312d12..18ae8e90d58cd2 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IncrementalGeneratorInitializationContextExtensions.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/IncrementalGeneratorInitializationContextExtensions.cs @@ -37,6 +37,14 @@ public static IncrementalValueProvider CreateStubEnvironmentPro new StubEnvironment(data.Right, data.Left.Left.TargetFramework, data.Left.Left.Version, data.Left.Right)); } + public static void RegisterDiagnostics(this IncrementalGeneratorInitializationContext context, IncrementalValuesProvider diagnostics) + { + context.RegisterSourceOutput(diagnostics.Where(diag => diag is not null), (context, diagnostic) => + { + context.ReportDiagnostic(diagnostic.ToDiagnostic()); + }); + } + public static void RegisterDiagnostics(this IncrementalGeneratorInitializationContext context, IncrementalValuesProvider diagnostics) { context.RegisterSourceOutput(diagnostics.Where(diag => diag is not null), (context, diagnostic) => diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MethodSignatureDiagnosticLocations.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MethodSignatureDiagnosticLocations.cs index 80607c56687224..3295ec367cb30d 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MethodSignatureDiagnosticLocations.cs +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/MethodSignatureDiagnosticLocations.cs @@ -9,7 +9,7 @@ namespace Microsoft.Interop { - public sealed record MethodSignatureDiagnosticLocations(string MethodIdentifier, ImmutableArray ManagedParameterLocations, Location FallbackLocation) + public sealed record MethodSignatureDiagnosticLocations(string MethodIdentifier, ImmutableArray ManagedParameterLocations, CodeAnalysis.Location FallbackLocation) { public MethodSignatureDiagnosticLocations(MethodDeclarationSyntax syntax) : this(syntax.Identifier.Text, syntax.ParameterList.Parameters.Select(p => p.Identifier.GetLocation()).ToImmutableArray(), syntax.Identifier.GetLocation()) diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj index 825fb6c60b8e3a..a1efa403dffbfa 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Microsoft.Interop.SourceGeneration.csproj @@ -17,6 +17,9 @@ + + + diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.cs.xlf b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.cs.xlf index 928b738e3978cb..cfe35f5450f5d1 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.cs.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.cs.xlf @@ -99,7 +99,7 @@ Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. - Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. + Zařazování řetězce nebo znaku bez explicitních informací o zařazování se nepodporuje. Zadejte „{0}. StringMarshalling“, „{0}. StringMarshallingCustomType“, „MarshalUsingAttribute“ nebo „MarshalAsAttribute.“ diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.de.xlf b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.de.xlf index 9380273ad22cf1..3401542f55361f 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.de.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.de.xlf @@ -99,7 +99,7 @@ Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. - Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. + Das Marshalling von Zeichenfolgen oder Zeichen ohne explizite Marshalling-Informationen wird nicht unterstützt. Geben Sie "{0}.StringMarshalling", "{0}.StringMarshallingCustomType", "MarshalUsingAttribute" oder "MarshalAsAttribute" an. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.es.xlf b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.es.xlf index 975e7598bc9c61..2dc4190d13752f 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.es.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.es.xlf @@ -99,7 +99,7 @@ Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. - Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. + No se admite la serialización de cadenas o caracteres sin información de serialización explícita. Especifique '{0}. StringMarshalling', '{0}. StringMars slaingCustomType", "MarshalUsingAttribute" o "MarshalAsAttribute". diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.fr.xlf b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.fr.xlf index f3eee5c5954ef0..f6d3df4388308f 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.fr.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.fr.xlf @@ -99,7 +99,7 @@ Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. - Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. + Le marshalling d’une chaîne ou d’un caractère sans information explicite sur le marshalling n’est pas pris en charge. Spécifiez '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' ou 'MarshalAsAttribute'. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.it.xlf b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.it.xlf index 35d51e7cc2eaa7..aca64f4d2bcb8d 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.it.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.it.xlf @@ -99,7 +99,7 @@ Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. - Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. + Il marshalling di stringa o carattere senza informazioni di marshalling esplicite non è supportato. Specificare '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' o 'MarshalAsAttribute'. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.ja.xlf b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.ja.xlf index 1931bd4f46a7a8..3c8601d2ef802b 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.ja.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.ja.xlf @@ -99,7 +99,7 @@ Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. - Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. + 明示的なマーシャリング情報を含まない文字列または文字のマーシャリングはサポートされていません。'{0}.StringMarshalling'、'{0}.StringMarshallingCustomType'、'MarshalUsingAttribute'、または 'MarshalAsAttribute'を指定します。 diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.ko.xlf b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.ko.xlf index e05123307f849c..2ebb10829a890f 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.ko.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.ko.xlf @@ -99,7 +99,7 @@ Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. - Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. + 명시적 마샬링 정보 없이 문자열 또는 char을 마샬링할 수 없습니다. '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' 또는 'MarshalAsAttribute'를 지정합니다. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.pl.xlf b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.pl.xlf index 7b0fdca47ad543..c3795cd9c6e54d 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.pl.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.pl.xlf @@ -99,7 +99,7 @@ Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. - Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. + Kierowanie ciągu lub znaku bez jawnych informacji o kierowaniu nie jest obsługiwane. Określ „{0}.StringMarshalling”, „{0}.StringMarshallingCustomType”, „MarshalUsingAttribute” lub „MarshalAsAttribute”. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.pt-BR.xlf b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.pt-BR.xlf index d9611fd6f2da11..881111b37d38c3 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.pt-BR.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.pt-BR.xlf @@ -99,7 +99,7 @@ Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. - Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. + Não há suporte para marshalling de cadeia de caracteres ou char sem informações de marshalling explícitas. Especifique ''{0}. StringMarshalling'', ''{0}. StringMarshallingCustomType'', ''MarshalUsingAttribute'' ou ''MarshalAsAttribute''. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.ru.xlf b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.ru.xlf index b1d7fc21a9f917..846b32913cc1c0 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.ru.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.ru.xlf @@ -99,7 +99,7 @@ Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. - Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. + Строка или символ со строкой или символом без явных сведений о маршалинге не поддерживаются. Укажите "{0}.StringMarshalling", "{0}.StringMarshallingCustomType", "MarshalUsingAttribute" или "MarshalAsAttribute". diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.tr.xlf b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.tr.xlf index 6c31b5e9c03ab2..296152917c0769 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.tr.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.tr.xlf @@ -99,7 +99,7 @@ Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. - Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. + Açık hazırlama bilgileri olmadan dize veya karakter hazırlama desteklenmiyor. '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' veya 'MarshalAsAttribute' belirtin. diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.zh-Hans.xlf b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.zh-Hans.xlf index e98fd3fb4996e8..2ca97730394c96 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.zh-Hans.xlf @@ -99,7 +99,7 @@ Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. - Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. + 不支持没有明确封送信息的封送字符串或字符。请指定“{0}.StringMarshalling”、“{0}.StringMarshallingCustomType”、“MarshalUsingAttribute”或“MarshalAsAttribute”。 diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.zh-Hant.xlf b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.zh-Hant.xlf index 857439822957eb..bbefc20455b229 100644 --- a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/Resources/xlf/Strings.zh-Hant.xlf @@ -99,7 +99,7 @@ Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. - Marshalling string or char without explicit marshalling information is not supported. Specify '{0}.StringMarshalling', '{0}.StringMarshallingCustomType', 'MarshalUsingAttribute' or 'MarshalAsAttribute'. + 不支援沒有明確封送處理資訊的封送處理字串或字元。請指定 '{0}.StringMarshalling、'{0}.StringMarshallingCustomType'、'MarshalUsingAttribute' 或 'MarshalAsAttribute'。 diff --git a/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ValueEqualityImmutableDictionary.cs b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ValueEqualityImmutableDictionary.cs new file mode 100644 index 00000000000000..f0a4b3737a08e3 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/gen/Microsoft.Interop.SourceGeneration/ValueEqualityImmutableDictionary.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; +using System.Collections; +using System.Collections.Generic; +using System.Collections.Immutable; + +namespace Microsoft.Interop +{ + public record struct ValueEqualityImmutableDictionary(ImmutableDictionary Map) : IDictionary + { + // Since this is immutable, we can cache the hash, which requires sorting and is expensive to calculate + private int? _hash = null; + + public bool Equals(ValueEqualityImmutableDictionary other) + { + if (Count != other.Count) + { + return false; + } + + foreach (var kvp in this) + { + if (!other.TryGetValue(kvp.Key, out var value) || !kvp.Value.Equals(value)) + { + return false; + } + } + return true; + } + + public override int GetHashCode() + { + if (_hash.HasValue) + return _hash.Value; + + _hash = 0; + foreach (var kvp in Map.ToImmutableArray().Sort()) + { + _hash = HashCode.Combine(_hash, kvp.Key, kvp.Value); + } + return _hash.Value; + } + + public U this[T key] { get => ((IDictionary)Map)[key]; set => ((IDictionary)Map)[key] = value; } + public ICollection Keys => ((IDictionary)Map).Keys; + public ICollection Values => ((IDictionary)Map).Values; + public int Count => Map.Count; + public bool IsReadOnly => ((ICollection>)Map).IsReadOnly; + public bool Contains(KeyValuePair item) => Map.Contains(item); + public bool ContainsKey(T key) => Map.ContainsKey(key); + public void CopyTo(KeyValuePair[] array, int arrayIndex) => ((ICollection>)Map).CopyTo(array, arrayIndex); + public IEnumerator> GetEnumerator() => ((IEnumerable>)Map).GetEnumerator(); + public bool Remove(T key) => ((IDictionary)Map).Remove(key); + public bool Remove(KeyValuePair item) => ((ICollection>)Map).Remove(item); + public bool TryGetValue(T key, out U value) => Map.TryGetValue(key, out value); + IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)Map).GetEnumerator(); + public void Add(T key, U value) => ((IDictionary)Map).Add(key, value); + public void Add(KeyValuePair item) => ((ICollection>)Map).Add(item); + public void Clear() => ((ICollection>)Map).Clear(); + } + + public static class ValueEqualityImmutableDictionaryHelperExtensions + { + public static ValueEqualityImmutableDictionary ToValueEqualityImmutableDictionary( + this IEnumerable source, + Func keySelector, + Func valueSelector) + { + return new ValueEqualityImmutableDictionary(source.ToImmutableDictionary(keySelector, valueSelector)); + } + public static ValueEqualityImmutableDictionary ToValueEquals(this ImmutableDictionary source) + { + return new ValueEqualityImmutableDictionary(source); + } + + } +} diff --git a/src/libraries/System.Runtime.InteropServices/src/Resources/Strings.resx b/src/libraries/System.Runtime.InteropServices/src/Resources/Strings.resx index 08d7e045a580f5..828dc3e2b9fe01 100644 --- a/src/libraries/System.Runtime.InteropServices/src/Resources/Strings.resx +++ b/src/libraries/System.Runtime.InteropServices/src/Resources/Strings.resx @@ -70,7 +70,7 @@ Event invocation for COM objects requires the declaring interface of the event to be attributed with ComEventInterfaceAttribute. - More than one ComEventInterfaceAttribute was found on the declaring interface of the event. + More than one ComEventInterfaceAttribute found for '{0}' on the declaring interface of the event. Event invocation for COM objects requires event to be attributed with DispIdAttribute. diff --git a/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/ComAwareEventInfo.cs b/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/ComAwareEventInfo.cs index 50fbb3bb523e6f..2ecc3eb7cc9c03 100644 --- a/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/ComAwareEventInfo.cs +++ b/src/libraries/System.Runtime.InteropServices/src/System/Runtime/InteropServices/ComAwareEventInfo.cs @@ -106,14 +106,15 @@ private static void GetDataForComInvocation(EventInfo eventInfo, out Guid source throw new InvalidOperationException(SR.InvalidOperation_NoComEventInterfaceAttribute); } + ComEventInterfaceAttribute interfaceAttribute = (ComEventInterfaceAttribute)comEventInterfaces[0]; + if (comEventInterfaces.Length > 1) { - throw new AmbiguousMatchException(SR.AmbiguousMatch_MultipleEventInterfaceAttributes); + throw new AmbiguousMatchException(SR.Format(SR.AmbiguousMatch_MultipleEventInterfaceAttributes, interfaceAttribute)); } - Type sourceInterface = ((ComEventInterfaceAttribute)comEventInterfaces[0]).SourceInterface; + Type sourceInterface = interfaceAttribute.SourceInterface; Guid guid = sourceInterface.GUID; - MethodInfo methodInfo = sourceInterface.GetMethod(eventInfo.Name)!; Attribute? dispIdAttribute = Attribute.GetCustomAttribute(methodInfo, typeof(DispIdAttribute)); if (dispIdAttribute == null) diff --git a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/StringMarshallingTests.cs b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/StringMarshallingTests.cs index 175296047f8456..c359be79f29679 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/StringMarshallingTests.cs +++ b/src/libraries/System.Runtime.InteropServices/tests/ComInterfaceGenerator.Tests/StringMarshallingTests.cs @@ -22,6 +22,9 @@ public unsafe partial class StringMarshallingTests [LibraryImport(NativeExportsNE.NativeExportsNE_Binary, EntryPoint = "new_utf16_marshalling")] public static partial void* NewIUtf16Marshalling(); + [LibraryImport(NativeExportsNE.NativeExportsNE_Binary, EntryPoint = "new_string_marshalling_override")] + public static partial void* NewStringMarshallingOverride(); + [GeneratedComClass] internal partial class Utf8MarshalledClass : IUTF8Marshalling { @@ -107,5 +110,26 @@ public void RcwToCcw() customUtf16ComObject.SetString("Set from COM object"); Assert.Equal(customUtf16.GetString(), customUtf16ComObject.GetString()); } + + [Fact] + public void MarshalAsAndMarshalUsingOverrideStringMarshalling() + { + var ptr = NewStringMarshallingOverride(); + var cw = new StrategyBasedComWrappers(); + var obj = cw.GetOrCreateObjectForComInstance((nint)ptr, CreateObjectFlags.None); + var stringMarshallingOverride = (IStringMarshallingOverride)obj; + Assert.Equal("Your string: MyUtf8String", stringMarshallingOverride.StringMarshallingUtf8("MyUtf8String")); + Assert.Equal("Your string: MyLPWStrString", stringMarshallingOverride.MarshalAsLPWString("MyLPWStrString")); + Assert.Equal("Your string: MyUtf16String", stringMarshallingOverride.MarshalUsingUtf16("MyUtf16String")); + + // Make sure the shadowing methods generated for the derived interface also follow the rules + var stringMarshallingOverrideDerived = (IStringMarshallingOverrideDerived)obj; + Assert.Equal("Your string: MyUtf8String", stringMarshallingOverrideDerived.StringMarshallingUtf8("MyUtf8String")); + Assert.Equal("Your string: MyLPWStrString", stringMarshallingOverrideDerived.MarshalAsLPWString("MyLPWStrString")); + Assert.Equal("Your string: MyUtf16String", stringMarshallingOverrideDerived.MarshalUsingUtf16("MyUtf16String")); + Assert.Equal("Your string 2: MyUtf8String", stringMarshallingOverrideDerived.StringMarshallingUtf8_2("MyUtf8String")); + Assert.Equal("Your string 2: MyLPWStrString", stringMarshallingOverrideDerived.MarshalAsLPWString_2("MyLPWStrString")); + Assert.Equal("Your string 2: MyUtf16String", stringMarshallingOverrideDerived.MarshalUsingUtf16_2("MyUtf16String")); + } } } diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/ComInterfaceGenerator/StringMarshallingOverride.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/ComInterfaceGenerator/StringMarshallingOverride.cs new file mode 100644 index 00000000000000..df01a1045700be --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/ComInterfaceGenerator/StringMarshallingOverride.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.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +using System.Text; +using System.Threading.Tasks; +using SharedTypes.ComInterfaces; +using static System.Runtime.InteropServices.ComWrappers; + +namespace NativeExports.ComInterfaceGenerator +{ + public unsafe partial class StringMarshallingOverride + { + [UnmanagedCallersOnly(EntryPoint = "new_string_marshalling_override")] + public static void* CreateStringMarshallingOverrideObject() + { + MyComWrapper cw = new(); + var myObject = new Implementation(); + nint ptr = cw.GetOrCreateComInterfaceForObject(myObject, CreateComInterfaceFlags.None); + return (void*)ptr; + } + + class MyComWrapper : ComWrappers + { + static void* _s_comInterfaceVTable = null; + static void* S_VTable + { + get + { + if (_s_comInterfaceVTable != null) + return _s_comInterfaceVTable; + void** vtable = (void**)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(GetAndSetInt), sizeof(void*) * 6); + GetIUnknownImpl(out var fpQueryInterface, out var fpAddReference, out var fpRelease); + vtable[0] = (void*)fpQueryInterface; + vtable[1] = (void*)fpAddReference; + vtable[2] = (void*)fpRelease; + vtable[3] = (delegate* unmanaged)&Implementation.ABI.StringMarshallingUtf8; + vtable[4] = (delegate* unmanaged)&Implementation.ABI.MarshalAsLPWStr; + vtable[5] = (delegate* unmanaged)&Implementation.ABI.MarshalUsingUtf16; + _s_comInterfaceVTable = vtable; + return _s_comInterfaceVTable; + } + } + + static void* _s_derivedVTable = null; + static void* S_DerivedVTable + { + get + { + if (_s_comInterfaceVTable != null) + return _s_comInterfaceVTable; + void** vtable = (void**)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(GetAndSetInt), sizeof(void*) * 9); + GetIUnknownImpl(out var fpQueryInterface, out var fpAddReference, out var fpRelease); + vtable[0] = (void*)fpQueryInterface; + vtable[1] = (void*)fpAddReference; + vtable[2] = (void*)fpRelease; + vtable[3] = (delegate* unmanaged)&Implementation.ABI.StringMarshallingUtf8; + vtable[4] = (delegate* unmanaged)&Implementation.ABI.MarshalAsLPWStr; + vtable[5] = (delegate* unmanaged)&Implementation.ABI.MarshalUsingUtf16; + vtable[6] = (delegate* unmanaged)&Implementation.ABI.StringMarshallingUtf8_2; + vtable[7] = (delegate* unmanaged)&Implementation.ABI.MarshalAsLPWStr_2; + vtable[8] = (delegate* unmanaged)&Implementation.ABI.MarshalUsingUtf16_2; + _s_comInterfaceVTable = vtable; + return _s_comInterfaceVTable; + } + } + + protected override ComInterfaceEntry* ComputeVtables(object obj, CreateComInterfaceFlags flags, out int count) + { + if (obj is IStringMarshallingOverrideDerived) + { + ComInterfaceEntry* comInterfaceEntry = (ComInterfaceEntry*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(Implementation), sizeof(ComInterfaceEntry) * 2); + comInterfaceEntry[0].IID = new Guid(IStringMarshallingOverrideDerived._guid); + comInterfaceEntry[0].Vtable = (nint)S_DerivedVTable; + comInterfaceEntry[1].IID = new Guid(IStringMarshallingOverride._guid); + comInterfaceEntry[1].Vtable = (nint)S_VTable; + count = 2; + return comInterfaceEntry; + } + if (obj is IStringMarshallingOverride) + { + ComInterfaceEntry* comInterfaceEntry = (ComInterfaceEntry*)RuntimeHelpers.AllocateTypeAssociatedMemory(typeof(Implementation), sizeof(ComInterfaceEntry)); + comInterfaceEntry->IID = new Guid(IStringMarshallingOverride._guid); + comInterfaceEntry->Vtable = (nint)S_VTable; + count = 1; + return comInterfaceEntry; + } + count = 0; + return null; + } + + protected override object? CreateObject(nint externalComObject, CreateObjectFlags flags) => throw new NotImplementedException(); + protected override void ReleaseObjects(IEnumerable objects) => throw new NotImplementedException(); + } + + partial class Implementation : IStringMarshallingOverride, IStringMarshallingOverrideDerived + { + string _data = "Your string: "; + string IStringMarshallingOverride.StringMarshallingUtf8(string input) => _data + input; + string IStringMarshallingOverride.MarshalAsLPWString(string input) => _data + input; + string IStringMarshallingOverride.MarshalUsingUtf16(string input) => _data + input; + + string _data2 = "Your string 2: "; + string IStringMarshallingOverrideDerived.StringMarshallingUtf8_2(string input) => _data2 + input; + string IStringMarshallingOverrideDerived.MarshalAsLPWString_2(string input) => _data2 + input; + string IStringMarshallingOverrideDerived.MarshalUsingUtf16_2(string input) => _data2 + input; + + // Provides function pointers in the COM format to use in COM VTables + public static class ABI + { + [UnmanagedCallersOnly] + public static int StringMarshallingUtf8(void* @this, byte* input, byte** output) + { + try + { + string inputStr = Utf8StringMarshaller.ConvertToManaged(input); + string currValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)@this).StringMarshallingUtf8(inputStr); + *output = Utf8StringMarshaller.ConvertToUnmanaged(currValue); + return 0; + } + catch (Exception e) + { + return e.HResult; + } + } + + [UnmanagedCallersOnly] + public static int MarshalAsLPWStr(void* @this, ushort* input, ushort** output) + { + try + { + string inputStr = Utf16StringMarshaller.ConvertToManaged(input); + string currValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)@this).MarshalAsLPWString(inputStr); + *output = Utf16StringMarshaller.ConvertToUnmanaged(currValue); + return 0; + } + catch (Exception e) + { + return e.HResult; + } + } + + [UnmanagedCallersOnly] + public static int MarshalUsingUtf16(void* @this, ushort* input, ushort** output) + { + try + { + string inputStr = Utf16StringMarshaller.ConvertToManaged(input); + string currValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)@this).MarshalUsingUtf16(inputStr); + *output = Utf16StringMarshaller.ConvertToUnmanaged(currValue); + return 0; + } + catch (Exception e) + { + return e.HResult; + } + } + + [UnmanagedCallersOnly] + public static int StringMarshallingUtf8_2(void* @this, byte* input, byte** output) + { + try + { + string inputStr = Utf8StringMarshaller.ConvertToManaged(input); + string currValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)@this).StringMarshallingUtf8_2(inputStr); + *output = Utf8StringMarshaller.ConvertToUnmanaged(currValue); + return 0; + } + catch (Exception e) + { + return e.HResult; + } + } + + [UnmanagedCallersOnly] + public static int MarshalAsLPWStr_2(void* @this, ushort* input, ushort** output) + { + try + { + string inputStr = Utf16StringMarshaller.ConvertToManaged(input); + string currValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)@this).MarshalAsLPWString_2(inputStr); + *output = Utf16StringMarshaller.ConvertToUnmanaged(currValue); + return 0; + } + catch (Exception e) + { + return e.HResult; + } + } + + [UnmanagedCallersOnly] + public static int MarshalUsingUtf16_2(void* @this, ushort* input, ushort** output) + { + try + { + string inputStr = Utf16StringMarshaller.ConvertToManaged(input); + string currValue = ComInterfaceDispatch.GetInstance((ComInterfaceDispatch*)@this).MarshalUsingUtf16_2(inputStr); + *output = Utf16StringMarshaller.ConvertToUnmanaged(currValue); + return 0; + } + catch (Exception e) + { + return e.HResult; + } + } + } + } + } +} 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 4ba1f17dd095ef..515dd2430360b2 100644 --- a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/NativeExports/NativeExports.csproj @@ -29,7 +29,7 @@ ExcludedRuntimeIdentifiers="android" AppHostPackNamePattern="Microsoft.NETCore.App.Host.**RID**" AppHostPackVersion="7.0.0" - AppHostRuntimeIdentifiers="linux-arm;linux-arm64;linux-musl-arm64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;tizen.4.0.0-armel;tizen.5.0.0-armel;win-arm;win-arm64;win-x64;win-x86;linux-musl-arm;osx-arm64;linux-s390x;linux-bionic-arm;linux-bionic-arm64;linux-bionic-x64;linux-bionic-x86" + AppHostRuntimeIdentifiers="linux-arm;linux-arm64;linux-musl-arm64;linux-musl-x64;linux-x64;osx-x64;rhel.6-x64;tizen.4.0.0-armel;tizen.5.0.0-armel;win-arm64;win-x64;win-x86;linux-musl-arm;osx-arm64;linux-s390x;linux-bionic-arm;linux-bionic-arm64;linux-bionic-x64;linux-bionic-x86" TargetFramework="$(NetCoreAppCurrent)" Condition="'@(KnownAppHostPack)' == '' or !@(KnownAppHostPack->AnyHaveMetadataValue('TargetFramework', '$(NetCoreAppCurrent)'))" /> diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStringMarshallingOverride.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStringMarshallingOverride.cs new file mode 100644 index 00000000000000..cd7c8f620dc935 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStringMarshallingOverride.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.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; +using System.Text; +using System.Threading.Tasks; + +namespace SharedTypes.ComInterfaces +{ + [GeneratedComInterface(StringMarshalling = System.Runtime.InteropServices.StringMarshalling.Utf8)] + [Guid(_guid)] + internal partial interface IStringMarshallingOverride + { + public const string _guid = "5146B7DB-0588-469B-B8E5-B38090A2FC15"; + string StringMarshallingUtf8(string input); + + [return: MarshalAs(UnmanagedType.LPWStr)] + string MarshalAsLPWString([MarshalAs(UnmanagedType.LPWStr)] string input); + + [return: MarshalUsing(typeof(Utf16StringMarshaller))] + string MarshalUsingUtf16([MarshalUsing(typeof(Utf16StringMarshaller))] string input); + } +} diff --git a/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStringMarshallingOverrideDerived.cs b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStringMarshallingOverrideDerived.cs new file mode 100644 index 00000000000000..079db461a66bd8 --- /dev/null +++ b/src/libraries/System.Runtime.InteropServices/tests/TestAssets/SharedTypes/ComInterfaces/IStringMarshallingOverrideDerived.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.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices.Marshalling; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace SharedTypes.ComInterfaces +{ + [GeneratedComInterface(StringMarshalling = StringMarshalling.Utf8)] + [Guid(_guid)] + internal partial interface IStringMarshallingOverrideDerived : IStringMarshallingOverride + { + public new const string _guid = "3AFFE3FD-D11E-4195-8250-0C73321977A0"; + string StringMarshallingUtf8_2(string input); + + [return: MarshalAs(UnmanagedType.LPWStr)] + string MarshalAsLPWString_2([MarshalAs(UnmanagedType.LPWStr)] string input); + + [return: MarshalUsing(typeof(Utf16StringMarshaller))] + string MarshalUsingUtf16_2([MarshalUsing(typeof(Utf16StringMarshaller))] string input); + } +} diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 518892678e02b1..f961d94d5e1454 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -14928,6 +14928,14 @@ public static void SetSafeWaitHandle(this System.Threading.WaitHandle waitHandle } namespace System.Threading.Tasks { + [System.FlagsAttribute] + public enum ConfigureAwaitOptions + { + None = 0x0, + ContinueOnCapturedContext = 0x1, + SuppressThrowing = 0x2, + ForceYielding = 0x4, + } public partial class ConcurrentExclusiveSchedulerPair { public ConcurrentExclusiveSchedulerPair() { } @@ -14965,6 +14973,7 @@ public Task(System.Action action, object? state, System.Threading.Tasks System.Threading.WaitHandle System.IAsyncResult.AsyncWaitHandle { get { throw null; } } bool System.IAsyncResult.CompletedSynchronously { get { throw null; } } public System.Runtime.CompilerServices.ConfiguredTaskAwaitable ConfigureAwait(bool continueOnCapturedContext) { throw null; } + public System.Runtime.CompilerServices.ConfiguredTaskAwaitable ConfigureAwait(System.Threading.Tasks.ConfigureAwaitOptions options) { throw null; } public System.Threading.Tasks.Task ContinueWith(System.Action continuationAction, object? state) { throw null; } public System.Threading.Tasks.Task ContinueWith(System.Action continuationAction, object? state, System.Threading.CancellationToken cancellationToken) { throw null; } public System.Threading.Tasks.Task ContinueWith(System.Action continuationAction, object? state, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; } @@ -15318,6 +15327,7 @@ public Task(System.Func function, System.Threading.Tasks.TaskCreationOp public static new System.Threading.Tasks.TaskFactory Factory { get { throw null; } } public TResult Result { get { throw null; } } public new System.Runtime.CompilerServices.ConfiguredTaskAwaitable ConfigureAwait(bool continueOnCapturedContext) { throw null; } + public new System.Runtime.CompilerServices.ConfiguredTaskAwaitable ConfigureAwait(System.Threading.Tasks.ConfigureAwaitOptions options) { throw null; } public System.Threading.Tasks.Task ContinueWith(System.Action, object?> continuationAction, object? state) { throw null; } public System.Threading.Tasks.Task ContinueWith(System.Action, object?> continuationAction, object? state, System.Threading.CancellationToken cancellationToken) { throw null; } public System.Threading.Tasks.Task ContinueWith(System.Action, object?> continuationAction, object? state, System.Threading.CancellationToken cancellationToken, System.Threading.Tasks.TaskContinuationOptions continuationOptions, System.Threading.Tasks.TaskScheduler scheduler) { throw null; } diff --git a/src/libraries/System.Runtime/tests/System/ArrayTests.cs b/src/libraries/System.Runtime/tests/System/ArrayTests.cs index db382d37030f05..7ef45b6401ad0e 100644 --- a/src/libraries/System.Runtime/tests/System/ArrayTests.cs +++ b/src/libraries/System.Runtime/tests/System/ArrayTests.cs @@ -263,38 +263,37 @@ public static IEnumerable BinarySearch_SZArray_TestData() yield return new object[] { new ulong[0], 0, 0, (ulong)0, null, -1 }; - // // [ActiveIssue("https://github.com/xunit/xunit/issues/1771")] - // // IntPtr + // IntPtr - // IntPtr[] intPtrArray = new IntPtr[] { IntPtr.MinValue, (IntPtr)0, (IntPtr)0, IntPtr.MaxValue }; + IntPtr[] intPtrArray = new IntPtr[] { IntPtr.MinValue, (IntPtr)0, (IntPtr)0, IntPtr.MaxValue }; - // yield return new object[] { intPtrArray, 0, 4, IntPtr.MinValue, null, 0 }; - // yield return new object[] { intPtrArray, 0, 4, (IntPtr)0, null, 1 }; - // yield return new object[] { intPtrArray, 0, 4, IntPtr.MaxValue, null, 3 }; - // yield return new object[] { intPtrArray, 0, 4, (IntPtr)1, null, -4 }; + yield return new object[] { intPtrArray, 0, 4, IntPtr.MinValue, null, 0 }; + yield return new object[] { intPtrArray, 0, 4, (IntPtr)0, null, 1 }; + yield return new object[] { intPtrArray, 0, 4, IntPtr.MaxValue, null, 3 }; + yield return new object[] { intPtrArray, 0, 4, (IntPtr)1, null, -4 }; - // yield return new object[] { intPtrArray, 0, 1, IntPtr.MinValue, null, 0 }; - // yield return new object[] { intPtrArray, 1, 3, IntPtr.MaxValue, null, 3 }; - // yield return new object[] { intPtrArray, 1, 3, IntPtr.MinValue, null, -2 }; - // yield return new object[] { intPtrArray, 1, 0, (IntPtr)0, null, -2 }; + yield return new object[] { intPtrArray, 0, 1, IntPtr.MinValue, null, 0 }; + yield return new object[] { intPtrArray, 1, 3, IntPtr.MaxValue, null, 3 }; + yield return new object[] { intPtrArray, 1, 3, IntPtr.MinValue, null, -2 }; + yield return new object[] { intPtrArray, 1, 0, (IntPtr)0, null, -2 }; - // yield return new object[] { new IntPtr[0], 0, 0, (IntPtr)0, null, -1 }; + yield return new object[] { new IntPtr[0], 0, 0, (IntPtr)0, null, -1 }; - // // UIntPtr + // UIntPtr - // UIntPtr[] uintPtrArray = new UIntPtr[] { UIntPtr.MinValue, (UIntPtr)5, (UIntPtr)5, UIntPtr.MaxValue }; + UIntPtr[] uintPtrArray = new UIntPtr[] { UIntPtr.MinValue, (UIntPtr)5, (UIntPtr)5, UIntPtr.MaxValue }; - // yield return new object[] { uintPtrArray, 0, 4, UIntPtr.MinValue, null, 0 }; - // yield return new object[] { uintPtrArray, 0, 4, (UIntPtr)5, null, 1 }; - // yield return new object[] { uintPtrArray, 0, 4, UIntPtr.MaxValue, null, 3 }; - // yield return new object[] { uintPtrArray, 0, 4, (UIntPtr)1, null, -2 }; + yield return new object[] { uintPtrArray, 0, 4, UIntPtr.MinValue, null, 0 }; + yield return new object[] { uintPtrArray, 0, 4, (UIntPtr)5, null, 1 }; + yield return new object[] { uintPtrArray, 0, 4, UIntPtr.MaxValue, null, 3 }; + yield return new object[] { uintPtrArray, 0, 4, (UIntPtr)1, null, -2 }; - // yield return new object[] { uintPtrArray, 0, 1, UIntPtr.MinValue, null, 0 }; - // yield return new object[] { uintPtrArray, 1, 3, UIntPtr.MaxValue, null, 3 }; - // yield return new object[] { uintPtrArray, 1, 3, UIntPtr.MinValue, null, -2 }; - // yield return new object[] { uintPtrArray, 1, 0, (UIntPtr)5, null, -2 }; + yield return new object[] { uintPtrArray, 0, 1, UIntPtr.MinValue, null, 0 }; + yield return new object[] { uintPtrArray, 1, 3, UIntPtr.MaxValue, null, 3 }; + yield return new object[] { uintPtrArray, 1, 3, UIntPtr.MinValue, null, -2 }; + yield return new object[] { uintPtrArray, 1, 0, (UIntPtr)5, null, -2 }; - // yield return new object[] { new UIntPtr[0], 0, 0, (UIntPtr)0, null, -1 }; + yield return new object[] { new UIntPtr[0], 0, 0, (UIntPtr)0, null, -1 }; // Char char[] charArray = new char[] { char.MinValue, (char)5, (char)5, char.MaxValue }; @@ -2361,25 +2360,23 @@ public static IEnumerable IndexOf_SZArray_TestData() yield return new object[] { new double[] { 1, 2, 3, 3 }, (double)1, 0, 0, -1 }; yield return new object[] { new double[0], (double)1, 0, 0, -1 }; - // [ActiveIssue("https://github.com/xunit/xunit/issues/1771")] // IntPtr - //yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3 }, (IntPtr)1, 0, 4, 0 }; - //yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3 }, (IntPtr)3, 0, 4, 2 }; - //yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3 }, (IntPtr)2, 1, 2, 1 }; - //yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3 }, (IntPtr)1, 1, 2, -1 }; - //yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3 }, (IntPtr)1, 4, 0, -1 }; - //yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3 }, (IntPtr)1, 0, 0, -1 }; - //yield return new object[] { new IntPtr[0], (IntPtr)1, 0, 0, -1 }; - - // [ActiveIssue("https://github.com/xunit/xunit/issues/1771")] + yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3 }, (IntPtr)1, 0, 4, 0 }; + yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3 }, (IntPtr)3, 0, 4, 2 }; + yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3 }, (IntPtr)2, 1, 2, 1 }; + yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3 }, (IntPtr)1, 1, 2, -1 }; + yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3 }, (IntPtr)1, 4, 0, -1 }; + yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3 }, (IntPtr)1, 0, 0, -1 }; + yield return new object[] { new IntPtr[0], (IntPtr)1, 0, 0, -1 }; + // UIntPtr - //yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3 }, (UIntPtr)1, 0, 4, 0 }; - //yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3 }, (UIntPtr)3, 0, 4, 2 }; - //yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3 }, (UIntPtr)2, 1, 2, 1 }; - //yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3 }, (UIntPtr)1, 1, 2, -1 }; - //yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3 }, (UIntPtr)1, 4, 0, -1 }; - //yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3 }, (UIntPtr)1, 0, 0, -1 }; - //yield return new object[] { new UIntPtr[0], (UIntPtr)1, 0, 0, -1 }; + yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3 }, (UIntPtr)1, 0, 4, 0 }; + yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3 }, (UIntPtr)3, 0, 4, 2 }; + yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3 }, (UIntPtr)2, 1, 2, 1 }; + yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3 }, (UIntPtr)1, 1, 2, -1 }; + yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3 }, (UIntPtr)1, 4, 0, -1 }; + yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3 }, (UIntPtr)1, 0, 0, -1 }; + yield return new object[] { new UIntPtr[0], (UIntPtr)1, 0, 0, -1 }; // String var stringArray = new string[] { null, null, "Hello", "Hello", "Goodbye", "Goodbye", null, null }; @@ -2739,25 +2736,23 @@ public static IEnumerable LastIndexOf_SZArray_TestData() yield return new object[] { new double[] { 1, 2, 3, 3, 4 }, (double)3, 0, 0, -1 }; yield return new object[] { new double[] { 1, 2, 3, 3, 4 }, (double)3, 3, 0, -1 }; - // [ActiveIssue("https://github.com/xunit/xunit/issues/1771")] // IntPtr - //yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3, (IntPtr)4 }, (IntPtr)1, 4, 5, 0 }; - //yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3, (IntPtr)4 }, (IntPtr)3, 4, 5, 3 }; - //yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3, (IntPtr)4 }, (IntPtr)2, 2, 3, 1 }; - //yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3, (IntPtr)4 }, (IntPtr)4, 2, 3, -1 }; - //yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3, (IntPtr)4 }, (IntPtr)5, 4, 5, -1 }; - //yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3, (IntPtr)4 }, (IntPtr)3, 0, 0, -1 }; - //yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3, (IntPtr)4 }, (IntPtr)3, 3, 0, -1 }; - - // [ActiveIssue("https://github.com/xunit/xunit/issues/1771")] + yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3, (IntPtr)4 }, (IntPtr)1, 4, 5, 0 }; + yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3, (IntPtr)4 }, (IntPtr)3, 4, 5, 3 }; + yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3, (IntPtr)4 }, (IntPtr)2, 2, 3, 1 }; + yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3, (IntPtr)4 }, (IntPtr)4, 2, 3, -1 }; + yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3, (IntPtr)4 }, (IntPtr)5, 4, 5, -1 }; + yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3, (IntPtr)4 }, (IntPtr)3, 0, 0, -1 }; + yield return new object[] { new IntPtr[] { (IntPtr)1, (IntPtr)2, (IntPtr)3, (IntPtr)3, (IntPtr)4 }, (IntPtr)3, 3, 0, -1 }; + // UIntPtr - //yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3, (UIntPtr)4 }, (UIntPtr)1, 4, 5, 0 }; - //yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3, (UIntPtr)4 }, (UIntPtr)3, 4, 5, 3 }; - //yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3, (UIntPtr)4 }, (UIntPtr)2, 2, 3, 1 }; - //yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3, (UIntPtr)4 }, (UIntPtr)4, 2, 3, -1 }; - //yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3, (UIntPtr)4 }, (UIntPtr)5, 4, 5, -1 }; - //yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3, (UIntPtr)4 }, (UIntPtr)3, 0, 0, -1 }; - //yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3, (UIntPtr)4 }, (UIntPtr)3, 3, 0, -1 }; + yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3, (UIntPtr)4 }, (UIntPtr)1, 4, 5, 0 }; + yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3, (UIntPtr)4 }, (UIntPtr)3, 4, 5, 3 }; + yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3, (UIntPtr)4 }, (UIntPtr)2, 2, 3, 1 }; + yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3, (UIntPtr)4 }, (UIntPtr)4, 2, 3, -1 }; + yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3, (UIntPtr)4 }, (UIntPtr)5, 4, 5, -1 }; + yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3, (UIntPtr)4 }, (UIntPtr)3, 0, 0, -1 }; + yield return new object[] { new UIntPtr[] { (UIntPtr)1, (UIntPtr)2, (UIntPtr)3, (UIntPtr)3, (UIntPtr)4 }, (UIntPtr)3, 3, 0, -1 }; // String var stringArray = new string[] { null, null, "Hello", "Hello", "Goodbye", "Goodbye", null, null }; diff --git a/src/libraries/System.Runtime/tests/System/Reflection/InvokeRefReturn.cs b/src/libraries/System.Runtime/tests/System/Reflection/InvokeRefReturn.cs index 48ea6f4bdfdf8c..bc30e86e050dc8 100644 --- a/src/libraries/System.Runtime/tests/System/Reflection/InvokeRefReturn.cs +++ b/src/libraries/System.Runtime/tests/System/Reflection/InvokeRefReturn.cs @@ -107,10 +107,9 @@ public static IEnumerable RefReturnInvokeTestData yield return new object[] { 42L }; yield return new object[] { 43.67f }; yield return new object[] { 43.67 }; - // [ActiveIssue("https://github.com/xunit/xunit/issues/1771")] - //yield return new object[] { new IntPtr(42) }; - //yield return new object[] { new UIntPtr(42) }; - //yield return new object[] { 232953453454m }; + yield return new object[] { new IntPtr(42) }; + yield return new object[] { new UIntPtr(42) }; + yield return new object[] { 232953453454m }; yield return new object[] { BindingFlags.IgnoreCase }; yield return new object[] { "Hello" }; yield return new object[] { new object() }; diff --git a/src/libraries/System.Runtime/tests/default.rd.xml b/src/libraries/System.Runtime/tests/default.rd.xml index c594df1579d567..cbfa5d3b58bd61 100644 --- a/src/libraries/System.Runtime/tests/default.rd.xml +++ b/src/libraries/System.Runtime/tests/default.rd.xml @@ -130,6 +130,9 @@ + + + @@ -176,6 +179,9 @@ + + + @@ -222,6 +228,9 @@ + + + @@ -243,6 +252,7 @@ + diff --git a/src/libraries/System.Security.Claims/src/System/Security/Claims/ClaimsIdentity.cs b/src/libraries/System.Security.Claims/src/System/Security/Claims/ClaimsIdentity.cs index c928dd88501eba..406fa2138bc3db 100644 --- a/src/libraries/System.Security.Claims/src/System/Security/Claims/ClaimsIdentity.cs +++ b/src/libraries/System.Security.Claims/src/System/Security/Claims/ClaimsIdentity.cs @@ -946,7 +946,7 @@ internal string DebuggerToString() claimsCount++; } - return $"Identity Name = {Name ?? "(null)"}, IsAuthenticated = {IsAuthenticated}, Claims Count = {claimsCount}"; + return $"Identity Name = {Name ?? "(null)"}, IsAuthenticated = {(IsAuthenticated ? "true" : "false")}, Claims Count = {claimsCount}"; } private sealed class ClaimsIdentityDebugProxy diff --git a/src/libraries/System.Security.Cryptography.Cng/tests/ECDiffieHellmanCngProvider.cs b/src/libraries/System.Security.Cryptography.Cng/tests/ECDiffieHellmanCngProvider.cs index d805dbc6d2b813..1dc38e42bccce8 100644 --- a/src/libraries/System.Security.Cryptography.Cng/tests/ECDiffieHellmanCngProvider.cs +++ b/src/libraries/System.Security.Cryptography.Cng/tests/ECDiffieHellmanCngProvider.cs @@ -36,6 +36,7 @@ public bool ExplicitCurvesSupported public bool CanDeriveNewPublicKey => true; public bool SupportsRawDerivation => PlatformDetection.IsWindows10OrLater; + public bool SupportsSha3 => PlatformDetection.SupportsSha3; private static bool NativeOidFriendlyNameExists(string oidFriendlyName) { diff --git a/src/libraries/System.Security.Cryptography.Cng/tests/RSACngProvider.cs b/src/libraries/System.Security.Cryptography.Cng/tests/RSACngProvider.cs index 963bd925d800c7..d41df34b61404b 100644 --- a/src/libraries/System.Security.Cryptography.Cng/tests/RSACngProvider.cs +++ b/src/libraries/System.Security.Cryptography.Cng/tests/RSACngProvider.cs @@ -36,6 +36,8 @@ public bool Supports384PrivateKey public bool SupportsPss => true; public bool SupportsSha1Signatures => true; + + public bool SupportsSha3 { get; } = SHA3_256.IsSupported; // If SHA3_256 is supported, assume 384 and 512 are, too. } public partial class RSAFactory diff --git a/src/libraries/System.Security.Cryptography.Csp/tests/RSACryptoServiceProviderProvider.cs b/src/libraries/System.Security.Cryptography.Csp/tests/RSACryptoServiceProviderProvider.cs index 7f4f3eb5b7d462..7cd358cd5d1213 100644 --- a/src/libraries/System.Security.Cryptography.Csp/tests/RSACryptoServiceProviderProvider.cs +++ b/src/libraries/System.Security.Cryptography.Csp/tests/RSACryptoServiceProviderProvider.cs @@ -23,6 +23,8 @@ public class RSACryptoServiceProviderProvider : IRSAProvider public bool SupportsPss => false; public bool SupportsSha1Signatures => _supportsSha1Signatures ??= SignatureSupport.CanProduceSha1Signature(Create()); + + public bool SupportsSha3 => false; } public partial class RSAFactory diff --git a/src/libraries/System.Security.Cryptography.OpenSsl/tests/EcDiffieHellmanOpenSslProvider.cs b/src/libraries/System.Security.Cryptography.OpenSsl/tests/EcDiffieHellmanOpenSslProvider.cs index ef4aa6f83881f5..0a7390c5b250ec 100644 --- a/src/libraries/System.Security.Cryptography.OpenSsl/tests/EcDiffieHellmanOpenSslProvider.cs +++ b/src/libraries/System.Security.Cryptography.OpenSsl/tests/EcDiffieHellmanOpenSslProvider.cs @@ -28,6 +28,7 @@ public ECDiffieHellman Create(ECCurve curve) public bool CanDeriveNewPublicKey => true; public bool SupportsRawDerivation => true; + public bool SupportsSha3 => PlatformDetection.SupportsSha3; } public partial class ECDiffieHellmanFactory diff --git a/src/libraries/System.Security.Cryptography.OpenSsl/tests/RSAOpenSslProvider.cs b/src/libraries/System.Security.Cryptography.OpenSsl/tests/RSAOpenSslProvider.cs index deeecbe7cb18bd..0adcda4bfad5ec 100644 --- a/src/libraries/System.Security.Cryptography.OpenSsl/tests/RSAOpenSslProvider.cs +++ b/src/libraries/System.Security.Cryptography.OpenSsl/tests/RSAOpenSslProvider.cs @@ -22,6 +22,8 @@ public class RSAOpenSslProvider : IRSAProvider public bool SupportsPss => true; public bool SupportsSha1Signatures => _supportsSha1Signatures ??= SignatureSupport.CanProduceSha1Signature(Create()); + + public bool SupportsSha3 => SHA3_256.IsSupported; // If SHA3_256 is supported, assume 384 and 512 are, too. } public partial class RSAFactory 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 8679d34557cf6b..10c6727f125668 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 @@ -69,6 +69,17 @@ internal static HashAlgorithmName GetDigestAlgorithm(string? oidValue, bool forV case Oids.Sha512: case Oids.RsaPkcs1Sha512 when forVerification: return HashAlgorithmName.SHA512; +#if NET8_0_OR_GREATER + case Oids.Sha3_256: + case Oids.RsaPkcs1Sha3_256 when forVerification: + return HashAlgorithmName.SHA3_256; + case Oids.Sha3_384: + case Oids.RsaPkcs1Sha3_384 when forVerification: + return HashAlgorithmName.SHA3_384; + case Oids.Sha3_512: + case Oids.RsaPkcs1Sha3_512 when forVerification: + return HashAlgorithmName.SHA3_512; +#endif default: throw new CryptographicException(SR.Cryptography_UnknownHashAlgorithm, oidValue); } @@ -86,6 +97,14 @@ internal static string GetOidFromHashAlgorithm(HashAlgorithmName algName) return Oids.Sha384; if (algName == HashAlgorithmName.SHA512) return Oids.Sha512; +#if NET8_0_OR_GREATER + if (algName == HashAlgorithmName.SHA3_256) + return Oids.Sha3_256; + if (algName == HashAlgorithmName.SHA3_384) + return Oids.Sha3_384; + if (algName == HashAlgorithmName.SHA3_512) + return Oids.Sha3_512; +#endif throw new CryptographicException(SR.Cryptography_Cms_UnknownAlgorithm, algName.Name); } 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 5fc08e0870e9b9..f9900fed9fb6a1 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 @@ -17,6 +17,11 @@ static partial void PrepareRegistrationECDsa(Dictionary lo lookup.Add(Oids.ECDsaWithSha256, new ECDsaCmsSignature(Oids.ECDsaWithSha256, HashAlgorithmName.SHA256)); lookup.Add(Oids.ECDsaWithSha384, new ECDsaCmsSignature(Oids.ECDsaWithSha384, HashAlgorithmName.SHA384)); lookup.Add(Oids.ECDsaWithSha512, new ECDsaCmsSignature(Oids.ECDsaWithSha512, HashAlgorithmName.SHA512)); +#if NET8_0_OR_GREATER + lookup.Add(Oids.ECDsaWithSha3_256, new ECDsaCmsSignature(Oids.ECDsaWithSha3_256, HashAlgorithmName.SHA3_256)); + lookup.Add(Oids.ECDsaWithSha3_384, new ECDsaCmsSignature(Oids.ECDsaWithSha3_384, HashAlgorithmName.SHA3_384)); + lookup.Add(Oids.ECDsaWithSha3_512, new ECDsaCmsSignature(Oids.ECDsaWithSha3_512, HashAlgorithmName.SHA3_512)); +#endif lookup.Add(Oids.EcPublicKey, new ECDsaCmsSignature(null, default)); } @@ -131,6 +136,11 @@ protected override bool Sign( hashAlgorithmName == HashAlgorithmName.SHA256 ? Oids.ECDsaWithSha256 : hashAlgorithmName == HashAlgorithmName.SHA384 ? Oids.ECDsaWithSha384 : hashAlgorithmName == HashAlgorithmName.SHA512 ? Oids.ECDsaWithSha512 : +#if NET8_0_OR_GREATER + hashAlgorithmName == HashAlgorithmName.SHA3_256 ? Oids.ECDsaWithSha3_256 : + hashAlgorithmName == HashAlgorithmName.SHA3_384 ? Oids.ECDsaWithSha3_384 : + hashAlgorithmName == HashAlgorithmName.SHA3_512 ? Oids.ECDsaWithSha3_512 : +#endif null; if (oidValue == null) 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 12adeda2360f6e..51677662dd5219 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 @@ -20,6 +20,11 @@ static partial void PrepareRegistrationRsa(Dictionary look lookup.Add(Oids.RsaPkcs1Sha256, new RSAPkcs1CmsSignature(Oids.RsaPkcs1Sha256, HashAlgorithmName.SHA256)); lookup.Add(Oids.RsaPkcs1Sha384, new RSAPkcs1CmsSignature(Oids.RsaPkcs1Sha384, HashAlgorithmName.SHA384)); lookup.Add(Oids.RsaPkcs1Sha512, new RSAPkcs1CmsSignature(Oids.RsaPkcs1Sha512, HashAlgorithmName.SHA512)); +#if NET8_0_OR_GREATER + lookup.Add(Oids.RsaPkcs1Sha3_256, new RSAPkcs1CmsSignature(Oids.RsaPkcs1Sha3_256, HashAlgorithmName.SHA3_256)); + lookup.Add(Oids.RsaPkcs1Sha3_384, new RSAPkcs1CmsSignature(Oids.RsaPkcs1Sha3_384, HashAlgorithmName.SHA3_384)); + lookup.Add(Oids.RsaPkcs1Sha3_512, new RSAPkcs1CmsSignature(Oids.RsaPkcs1Sha3_512, HashAlgorithmName.SHA3_512)); +#endif lookup.Add(Oids.RsaPss, new RSAPssCmsSignature()); } 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 0d2360240469ea..32d6262e18c085 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 @@ -185,7 +185,18 @@ internal SignerInfoAsn Sign( newSignerInfo.DigestAlgorithm.Algorithm = DigestAlgorithm.Value!; byte[] dataHash; - using (IncrementalHash hasher = IncrementalHash.CreateHash(hashAlgorithmName)) + IncrementalHash hasher; + + try + { + hasher = IncrementalHash.CreateHash(hashAlgorithmName); + } + catch (PlatformNotSupportedException ex) + { + throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmName), ex); + } + + using (hasher) { hasher.AppendData(data.Span); dataHash = hasher.GetHashAndReset(); 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 2ee1049b965d6e..021e1f8e9be2d4 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 @@ -550,7 +550,17 @@ private bool CheckHash(bool compatMode) { HashAlgorithmName hashAlgorithmName = GetDigestAlgorithm(); - IncrementalHash hasher = IncrementalHash.CreateHash(hashAlgorithmName); + + IncrementalHash hasher; + + try + { + hasher = IncrementalHash.CreateHash(hashAlgorithmName); + } + catch (PlatformNotSupportedException ex) + { + throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmName), ex); + } if (_parentSignerInfo == null) { diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/Oids.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/Oids.cs index eded07b0913ebd..bcaa73082ebfc7 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/Oids.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/Oids.cs @@ -63,6 +63,9 @@ internal static class Oids public const string Sha256 = "2.16.840.1.101.3.4.2.1"; public const string Sha384 = "2.16.840.1.101.3.4.2.2"; public const string Sha512 = "2.16.840.1.101.3.4.2.3"; + public const string Sha3_256 = "2.16.840.1.101.3.4.2.8"; + public const string Sha3_384 = "2.16.840.1.101.3.4.2.9"; + public const string Sha3_512 = "2.16.840.1.101.3.4.2.10"; // RFC3161 Timestamping public const string TstInfo = "1.2.840.113549.1.9.16.1.4"; diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.netcoreapp.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.netcoreapp.cs index 8ede25072e17e9..355d9e5763557d 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.netcoreapp.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedCmsTests.netcoreapp.cs @@ -691,6 +691,138 @@ public static void ComputeSignature_PreservesAttributeCertificate() Assert.Equal(countBefore + 1, countAfter); } + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.SupportsSha3))] + [InlineData(Oids.Sha3_256)] + [InlineData(Oids.Sha3_384)] + [InlineData(Oids.Sha3_512)] + public static void ComputeSignature_Rsa_Sha3_Roundtrip(string hashAlgorithm) + { + ContentInfo content = new ContentInfo(new byte[] { 1, 2, 3 }); + SignedCms cms = new SignedCms(content); + byte[] cmsBytes; + + using (X509Certificate2 cert = Certificates.RSA2048SignatureOnly.TryGetCertificateWithPrivateKey()) + { + CmsSigner signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, cert); + signer.DigestAlgorithm = new Oid(hashAlgorithm, null); + + cms.ComputeSignature(signer); + cmsBytes = cms.Encode(); + cms = new SignedCms(); + cms.Decode(cmsBytes); + cms.CheckSignature(true); // Assert.NoThrow + Assert.Single(cms.SignerInfos); + + SignerInfo signerInfo = cms.SignerInfos[0]; + Assert.Equal(hashAlgorithm, signerInfo.DigestAlgorithm.Value); + } + } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.SupportsSha3))] + [InlineData(Oids.Sha3_256)] + [InlineData(Oids.Sha3_384)] + [InlineData(Oids.Sha3_512)] + public static void ComputeSignature_Ecdsa_Sha3_Roundtrip(string hashAlgorithm) + { + ContentInfo content = new ContentInfo(new byte[] { 1, 2, 3 }); + SignedCms cms = new SignedCms(content); + byte[] cmsBytes; + + using (X509Certificate2 cert = Certificates.ECDsaP521Win.TryGetCertificateWithPrivateKey()) + { + CmsSigner signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, cert); + signer.DigestAlgorithm = new Oid(hashAlgorithm, null); + + cms.ComputeSignature(signer); + cmsBytes = cms.Encode(); + cms = new SignedCms(); + cms.Decode(cmsBytes); + cms.CheckSignature(true); // Assert.NoThrow + Assert.Single(cms.SignerInfos); + + SignerInfo signerInfo = cms.SignerInfos[0]; + Assert.Equal(hashAlgorithm, signerInfo.DigestAlgorithm.Value); + } + } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.DoesNotSupportSha3))] + [InlineData(Oids.Sha3_256)] + [InlineData(Oids.Sha3_384)] + [InlineData(Oids.Sha3_512)] + public static void ComputeSignature_Sha3_NotSupported(string hashAlgorithm) + { + ContentInfo content = new ContentInfo(new byte[] { 1, 2, 3 }); + SignedCms cms = new SignedCms(content); + + using (X509Certificate2 cert = Certificates.RSA2048SignatureOnly.TryGetCertificateWithPrivateKey()) + { + CmsSigner signer = new CmsSigner(SubjectIdentifierType.IssuerAndSerialNumber, cert); + signer.DigestAlgorithm = new Oid(hashAlgorithm, null); + + Assert.Throws(() => cms.ComputeSignature(signer)); + } + } + + [Fact] + public static void ExistingDocument_Rsa_Sha3_256() + { + SignedCms cms = new SignedCms(); + cms.Decode(SignedDocuments.Rsa_Sha3_256_SignedDocument); + + if (PlatformDetection.SupportsSha3) + { + cms.CheckSignature(true); // Assert.NoThrow + Assert.Single(cms.SignerInfos); + + SignerInfo signerInfo = cms.SignerInfos[0]; + Assert.Equal(Oids.Sha3_256, signerInfo.DigestAlgorithm.Value); + } + else + { + Assert.Throws(() => cms.CheckSignature(true)); + } + } + + [Fact] + public static void ExistingDocument_Rsa_Sha3_384() + { + SignedCms cms = new SignedCms(); + cms.Decode(SignedDocuments.Rsa_Sha3_384_SignedDocument); + + if (PlatformDetection.SupportsSha3) + { + cms.CheckSignature(true); // Assert.NoThrow + Assert.Single(cms.SignerInfos); + + SignerInfo signerInfo = cms.SignerInfos[0]; + Assert.Equal(Oids.Sha3_384, signerInfo.DigestAlgorithm.Value); + } + else + { + Assert.Throws(() => cms.CheckSignature(true)); + } + } + + [Fact] + public static void ExistingDocument_Rsa_Sha3_512() + { + SignedCms cms = new SignedCms(); + cms.Decode(SignedDocuments.Rsa_Sha3_512_SignedDocument); + + if (PlatformDetection.SupportsSha3) + { + cms.CheckSignature(true); // Assert.NoThrow + Assert.Single(cms.SignerInfos); + + SignerInfo signerInfo = cms.SignerInfos[0]; + Assert.Equal(Oids.Sha3_512, signerInfo.DigestAlgorithm.Value); + } + else + { + Assert.Throws(() => cms.CheckSignature(true)); + } + } + private static void VerifyWithExplicitPrivateKey(X509Certificate2 cert, AsymmetricAlgorithm key) { using (var pubCert = new X509Certificate2(cert.RawData)) diff --git a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedDocuments.cs b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedDocuments.cs index cce3114824794e..7001b325cd4029 100644 --- a/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedDocuments.cs +++ b/src/libraries/System.Security.Cryptography.Pkcs/tests/SignedCms/SignedDocuments.cs @@ -1626,5 +1626,168 @@ internal static class SignedDocuments "6AB46C76047604BA7DF071EE0137B73F4D9DF616095C8F1CA9EB925B6D4C6ABC" + "FFEB73A81903169C6B487B316AFC951F696831A4B29B9ABCEA7EBCD243A553D2" + "F8B44FDA1B0AC0").HexToByteArray(); + + // produced with + // echo -n hello | openssl cms -sign -signer cert.pfx -md sha3-256 -nodetach + internal static readonly byte[] Rsa_Sha3_256_SignedDocument =( + "308205C806092A864886F70D010702A08205B9308205B5020101310D300B" + + "0609608648016503040208301406092A864886F70D010701A00704056865" + + "6C6C6FA08203303082032C30820214A003020102020900E0D8AB6819D730" + + "6E300D06092A864886F70D01010B05003038313630340603550403132D54" + + "776F2074686F7573616E6420666F7274792065696768742062697473206F" + + "662052534120676F6F646E657373301E170D313731313033323335313135" + + "5A170D3138313130333233353131355A3038313630340603550403132D54" + + "776F2074686F7573616E6420666F7274792065696768742062697473206F" + + "662052534120676F6F646E65737330820122300D06092A864886F70D0101" + + "0105000382010F003082010A028201010096C114A5898D09133EF859F89C" + + "1D848BA8CB5258793E05B92D499C55EEFACE274BBBC26803FB813B9C11C6" + + "898153CC1745DED2C4D2672F807F0B2D957BC4B65EBC9DDE26E2EA7B2A6F" + + "E9A7C4D8BD1EF6032B8F0BB6AA33C8B57248B3D5E3901D8A38A283D7E25F" + + "F8E6F522381EE5484234CFF7B30C174635418FA89E14C468AD89DCFCBBB5" + + "35E5AF53510F9EA7F9DA8C1B53375B6DAB95A291439A5648726EE1012E41" + + "388E100691642CF6917F5569D8351F2782F435A579014E8448EEA0C4AECA" + + "FF2F476799D88457E2C8BCB56E5E128782B4FE26AFF0720D91D52CCAFE34" + + "4255808F5271D09F784F787E8323182080915BE0AE15A71D66476D0F264D" + + "D084F30203010001A3393037301D0603551D0E04160414745B5F12EF962E" + + "84B897E246D399A2BADEA9C5AC30090603551D1304023000300B0603551D" + + "0F040403020780300D06092A864886F70D01010B0500038201010087A15D" + + "F37FBD6E9DED7A8FFF25E60B731F635469BA01DD14BC03B2A24D99EFD8B8" + + "94E9493D63EC88C496CB04B33DF25222544F23D43F4023612C4D97B719C1" + + "F9431E4DB7A580CDF66A3E5F0DAF89A267DD187ABFFB08361B1F79232376" + + "AA5FC5AD384CC2F98FE36C1CEA0B943E1E3961190648889C8ABE8397A5A3" + + "38843CBFB1D8B212BE46685ACE7B80475CC7C97FC0377936ABD5F664E9C0" + + "9C463897726650711A1110FA9866BC1C278D95E5636AB96FAE95CCD67FD5" + + "72A8C727E2C03E7B242457318BEC1BE52CA5BD9454A0A41140AE96ED1C56" + + "D220D1FD5DD3B1B4FB2AA0E04FC94F7E3C7D476F298962245563953AD722" + + "5EDCEAC8B8509E49292E62D8BF3182025530820251020101304530383136" + + "30340603550403132D54776F2074686F7573616E6420666F727479206569" + + "6768742062697473206F662052534120676F6F646E657373020900E0D8AB" + + "6819D7306E300B0609608648016503040208A081E4301806092A864886F7" + + "0D010903310B06092A864886F70D010701301C06092A864886F70D010905" + + "310F170D3233303531373139333732315A302F06092A864886F70D010904" + + "312204203338BE694F50C5F338814986CDF0686453A888B84F424D792AF4" + + "B9202398F392307906092A864886F70D01090F316C306A300B0609608648" + + "01650304012A300B0609608648016503040116300B060960864801650304" + + "0102300A06082A864886F70D0307300E06082A864886F70D030202020080" + + "300D06082A864886F70D0302020140300706052B0E030207300D06082A86" + + "4886F70D0302020128300D06092A864886F70D0101010500048201002CDE" + + "D12EA41BA5443CE742A804E754D00AA8A21B4B9022780DF59BD597EA44DD" + + "85EEE42AA531A645CD11CAA58297190C06A8193CE7AF16B1FD8B9DF4E2FA" + + "15024E8E845D0E3537577C6F27CEB3317D57781B618388FFB61926D24B1F" + + "75E0CC460C52FFB43D8DDA1B7AFBCD76C00EECF99F7F7D2A02B19A055C9B" + + "A5437ADE06537F4194F15AD0C5071F0275128B435B8883FE8E2E07F6B908" + + "33B9FB56015FE57B3BEC08A5B9031AB8D372C662DCA6E3CDEA5D3F3FC76E" + + "02F8E52045386B8D83D46C6300F5B54B2135F6392DD0B6A9C5531E7C9405" + + "B48BF1DA5C5C7B9D6E00937673C7C97DB3B2DB6945D7C8F0F8E455AAF4DF" + + "6F7D7A7726B09B6025ED6DE21864").HexToByteArray(); + + // produced with + // echo -n hello | openssl cms -sign -signer cert.pfx -md sha3-384 -nodetach + internal static readonly byte[] Rsa_Sha3_384_SignedDocument = ( + "308205D806092A864886F70D010702A08205C9308205C5020101310D300B" + + "0609608648016503040209301406092A864886F70D010701A00704056865" + + "6C6C6FA08203303082032C30820214A003020102020900E0D8AB6819D730" + + "6E300D06092A864886F70D01010B05003038313630340603550403132D54" + + "776F2074686F7573616E6420666F7274792065696768742062697473206F" + + "662052534120676F6F646E657373301E170D313731313033323335313135" + + "5A170D3138313130333233353131355A3038313630340603550403132D54" + + "776F2074686F7573616E6420666F7274792065696768742062697473206F" + + "662052534120676F6F646E65737330820122300D06092A864886F70D0101" + + "0105000382010F003082010A028201010096C114A5898D09133EF859F89C" + + "1D848BA8CB5258793E05B92D499C55EEFACE274BBBC26803FB813B9C11C6" + + "898153CC1745DED2C4D2672F807F0B2D957BC4B65EBC9DDE26E2EA7B2A6F" + + "E9A7C4D8BD1EF6032B8F0BB6AA33C8B57248B3D5E3901D8A38A283D7E25F" + + "F8E6F522381EE5484234CFF7B30C174635418FA89E14C468AD89DCFCBBB5" + + "35E5AF53510F9EA7F9DA8C1B53375B6DAB95A291439A5648726EE1012E41" + + "388E100691642CF6917F5569D8351F2782F435A579014E8448EEA0C4AECA" + + "FF2F476799D88457E2C8BCB56E5E128782B4FE26AFF0720D91D52CCAFE34" + + "4255808F5271D09F784F787E8323182080915BE0AE15A71D66476D0F264D" + + "D084F30203010001A3393037301D0603551D0E04160414745B5F12EF962E" + + "84B897E246D399A2BADEA9C5AC30090603551D1304023000300B0603551D" + + "0F040403020780300D06092A864886F70D01010B0500038201010087A15D" + + "F37FBD6E9DED7A8FFF25E60B731F635469BA01DD14BC03B2A24D99EFD8B8" + + "94E9493D63EC88C496CB04B33DF25222544F23D43F4023612C4D97B719C1" + + "F9431E4DB7A580CDF66A3E5F0DAF89A267DD187ABFFB08361B1F79232376" + + "AA5FC5AD384CC2F98FE36C1CEA0B943E1E3961190648889C8ABE8397A5A3" + + "38843CBFB1D8B212BE46685ACE7B80475CC7C97FC0377936ABD5F664E9C0" + + "9C463897726650711A1110FA9866BC1C278D95E5636AB96FAE95CCD67FD5" + + "72A8C727E2C03E7B242457318BEC1BE52CA5BD9454A0A41140AE96ED1C56" + + "D220D1FD5DD3B1B4FB2AA0E04FC94F7E3C7D476F298962245563953AD722" + + "5EDCEAC8B8509E49292E62D8BF3182026530820261020101304530383136" + + "30340603550403132D54776F2074686F7573616E6420666F727479206569" + + "6768742062697473206F662052534120676F6F646E657373020900E0D8AB" + + "6819D7306E300B0609608648016503040209A081F4301806092A864886F7" + + "0D010903310B06092A864886F70D010701301C06092A864886F70D010905" + + "310F170D3233303531373139353133375A303F06092A864886F70D010904" + + "31320430720AEA11019EF06440FBF05D87AA24680A2153DF3907B23631E7" + + "177CE620FA1330FF07C0FDDEE54699A4C3EE0EE9D887307906092A864886" + + "F70D01090F316C306A300B060960864801650304012A300B060960864801" + + "6503040116300B0609608648016503040102300A06082A864886F70D0307" + + "300E06082A864886F70D030202020080300D06082A864886F70D03020201" + + "40300706052B0E030207300D06082A864886F70D0302020128300D06092A" + + "864886F70D010101050004820100208BB078601C3AA70070F74E70D34C73" + + "90CC21B06CB5566708C9287F191C08E71D476ABFBCE52AE21286D114746D" + + "B1CD32F5D1738347305CEEC67332F4B9B2B272183719212562FADFE4AD81" + + "1C257220EFB0E59C271D6006AA332175CAFEB295A53BC3148156D07312DB" + + "B215307DE92BC00BD45B3E819CF15F50F05AD34EC855A1387BBE11AF6200" + + "5E1AB04CE442BB9A14490D2BA96E8490E94BC10CFC0F32671443F9EB6E6C" + + "4AAE7F036D1CD4FB93AEFAFCFA98F705298157921304D1066A723671FF9A" + + "A63C6B06E2FA16763F1A8D5A9B048BBEF5C5BF6906615A9C279532FF6AAC" + + "45361541683350FF343D3496C79EE503F1D1BF60F9CBBB562F14DCC4B80A").HexToByteArray(); + + // produced with + // echo -n hello | openssl cms -sign -signer cert.pfx -md sha3-512 -nodetach + internal static readonly byte[] Rsa_Sha3_512_SignedDocument = ( + "308205E906092A864886F70D010702A08205DA308205D6020101310D300B" + + "060960864801650304020A301406092A864886F70D010701A00704056865" + + "6C6C6FA08203303082032C30820214A003020102020900E0D8AB6819D730" + + "6E300D06092A864886F70D01010B05003038313630340603550403132D54" + + "776F2074686F7573616E6420666F7274792065696768742062697473206F" + + "662052534120676F6F646E657373301E170D313731313033323335313135" + + "5A170D3138313130333233353131355A3038313630340603550403132D54" + + "776F2074686F7573616E6420666F7274792065696768742062697473206F" + + "662052534120676F6F646E65737330820122300D06092A864886F70D0101" + + "0105000382010F003082010A028201010096C114A5898D09133EF859F89C" + + "1D848BA8CB5258793E05B92D499C55EEFACE274BBBC26803FB813B9C11C6" + + "898153CC1745DED2C4D2672F807F0B2D957BC4B65EBC9DDE26E2EA7B2A6F" + + "E9A7C4D8BD1EF6032B8F0BB6AA33C8B57248B3D5E3901D8A38A283D7E25F" + + "F8E6F522381EE5484234CFF7B30C174635418FA89E14C468AD89DCFCBBB5" + + "35E5AF53510F9EA7F9DA8C1B53375B6DAB95A291439A5648726EE1012E41" + + "388E100691642CF6917F5569D8351F2782F435A579014E8448EEA0C4AECA" + + "FF2F476799D88457E2C8BCB56E5E128782B4FE26AFF0720D91D52CCAFE34" + + "4255808F5271D09F784F787E8323182080915BE0AE15A71D66476D0F264D" + + "D084F30203010001A3393037301D0603551D0E04160414745B5F12EF962E" + + "84B897E246D399A2BADEA9C5AC30090603551D1304023000300B0603551D" + + "0F040403020780300D06092A864886F70D01010B0500038201010087A15D" + + "F37FBD6E9DED7A8FFF25E60B731F635469BA01DD14BC03B2A24D99EFD8B8" + + "94E9493D63EC88C496CB04B33DF25222544F23D43F4023612C4D97B719C1" + + "F9431E4DB7A580CDF66A3E5F0DAF89A267DD187ABFFB08361B1F79232376" + + "AA5FC5AD384CC2F98FE36C1CEA0B943E1E3961190648889C8ABE8397A5A3" + + "38843CBFB1D8B212BE46685ACE7B80475CC7C97FC0377936ABD5F664E9C0" + + "9C463897726650711A1110FA9866BC1C278D95E5636AB96FAE95CCD67FD5" + + "72A8C727E2C03E7B242457318BEC1BE52CA5BD9454A0A41140AE96ED1C56" + + "D220D1FD5DD3B1B4FB2AA0E04FC94F7E3C7D476F298962245563953AD722" + + "5EDCEAC8B8509E49292E62D8BF3182027630820272020101304530383136" + + "30340603550403132D54776F2074686F7573616E6420666F727479206569" + + "6768742062697473206F662052534120676F6F646E657373020900E0D8AB" + + "6819D7306E300B060960864801650304020AA0820104301806092A864886" + + "F70D010903310B06092A864886F70D010701301C06092A864886F70D0109" + + "05310F170D3233303531373139353830395A304F06092A864886F70D0109" + + "043142044075D527C368F2EFE848ECF6B073A36767800805E9EEF2B1857D" + + "5F984F036EB6DF891D75F72D9B154518C1CD58835286D1DA9A38DEBA3DE9" + + "8B5A53E5ED78A84976307906092A864886F70D01090F316C306A300B0609" + + "60864801650304012A300B0609608648016503040116300B060960864801" + + "6503040102300A06082A864886F70D0307300E06082A864886F70D030202" + + "020080300D06082A864886F70D0302020140300706052B0E030207300D06" + + "082A864886F70D0302020128300D06092A864886F70D0101010500048201" + + "002E3AA896EB261EE1E8A552B4D5F7A466332EBAF90B74E2E563EC939E2C" + + "C4494D8A6C27BE9D23FD009EA4CD3734E3E5BFED0845156FBC2D520A223D" + + "17113658948955A0D95B1B8D7683D1A5E1AD6C41C8E4572C1D74D1B56B3E" + + "5E17E2E05AF4AA34919F34B01EB93C6614D0781CCE28B3281C9E10FEB5CE" + + "D0280E1B86761E06A315F027577DA15EDBBA19FC2095AC4D970FE718EAE8" + + "7F4AD106E6F4C674FD1958EE16EE07C54DAB405EC7A7A55A6D3B665427D4" + + "F11C632B4F605A41821A3F15B4F537FD5F0EE3426A7A03732AC946C3B435" + + "776A873A3DAE93FB8312C681144CF51F05CE37A0DB4C1544E178F88E421C" + + "0B5456D18C13B335DA808CE60C4E35F507").HexToByteArray(); } } diff --git a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Reference.cs b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Reference.cs index a0dc3399730e19..ba3a46bc7a7a43 100644 --- a/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Reference.cs +++ b/src/libraries/System.Security.Cryptography.Xml/src/System/Security/Cryptography/Xml/Reference.cs @@ -149,6 +149,8 @@ internal ReferenceTargetType ReferenceTargetType } } + private static readonly string[] s_expectedAttrNames = new string[] { "Id", "URI", "Type" }; + // // public methods // @@ -214,7 +216,7 @@ public void LoadXml(XmlElement value) _id = Utils.GetAttribute(value, "Id", SignedXml.XmlDsigNamespaceUrl); _uri = Utils.GetAttribute(value, "URI", SignedXml.XmlDsigNamespaceUrl); _type = Utils.GetAttribute(value, "Type", SignedXml.XmlDsigNamespaceUrl); - if (!Utils.VerifyAttributes(value, new string[] { "Id", "URI", "Type" })) + if (!Utils.VerifyAttributes(value, s_expectedAttrNames)) throw new CryptographicException(SR.Cryptography_Xml_InvalidElement, "Reference"); XmlNamespaceManager nsm = new XmlNamespaceManager(value.OwnerDocument.NameTable); 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 425b0e39888d8f..780a37489a23ff 100644 --- a/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs +++ b/src/libraries/System.Security.Cryptography/ref/System.Security.Cryptography.cs @@ -1321,6 +1321,9 @@ protected virtual void HashCore(System.ReadOnlySpan source) { } public static System.Security.Cryptography.HashAlgorithmName SHA1 { get { throw null; } } public static System.Security.Cryptography.HashAlgorithmName SHA256 { get { throw null; } } public static System.Security.Cryptography.HashAlgorithmName SHA384 { get { throw null; } } + public static System.Security.Cryptography.HashAlgorithmName SHA3_256 { get { throw null; } } + public static System.Security.Cryptography.HashAlgorithmName SHA3_384 { get { throw null; } } + public static System.Security.Cryptography.HashAlgorithmName SHA3_512 { get { throw null; } } public static System.Security.Cryptography.HashAlgorithmName SHA512 { get { throw null; } } public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? obj) { throw null; } public bool Equals(System.Security.Cryptography.HashAlgorithmName other) { throw null; } @@ -1471,6 +1474,81 @@ public override void Initialize() { } public static bool TryHashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { throw null; } protected override bool TryHashFinal(System.Span destination, out int bytesWritten) { throw null; } } + public partial class HMACSHA3_256 : System.Security.Cryptography.HMAC + { + public const int HashSizeInBits = 256; + public const int HashSizeInBytes = 32; + public HMACSHA3_256() { } + public HMACSHA3_256(byte[] key) { } + public static bool IsSupported { get { throw null; } } + public override byte[] Key { get { throw null; } set { } } + protected override void Dispose(bool disposing) { } + protected override void HashCore(byte[] rgb, int ib, int cb) { } + protected override void HashCore(System.ReadOnlySpan source) { } + public static byte[] HashData(byte[] key, byte[] source) { throw null; } + public static byte[] HashData(byte[] key, System.IO.Stream source) { throw null; } + public static byte[] HashData(System.ReadOnlySpan key, System.IO.Stream source) { throw null; } + public static int HashData(System.ReadOnlySpan key, System.IO.Stream source, System.Span destination) { throw null; } + public static byte[] HashData(System.ReadOnlySpan key, System.ReadOnlySpan source) { throw null; } + public static int HashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(byte[] key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + protected override byte[] HashFinal() { throw null; } + public override void Initialize() { } + public static bool TryHashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { throw null; } + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) { throw null; } + } + public partial class HMACSHA3_384 : System.Security.Cryptography.HMAC + { + public const int HashSizeInBits = 384; + public const int HashSizeInBytes = 48; + public HMACSHA3_384() { } + public HMACSHA3_384(byte[] key) { } + public static bool IsSupported { get { throw null; } } + public override byte[] Key { get { throw null; } set { } } + protected override void Dispose(bool disposing) { } + protected override void HashCore(byte[] rgb, int ib, int cb) { } + protected override void HashCore(System.ReadOnlySpan source) { } + public static byte[] HashData(byte[] key, byte[] source) { throw null; } + public static byte[] HashData(byte[] key, System.IO.Stream source) { throw null; } + public static byte[] HashData(System.ReadOnlySpan key, System.IO.Stream source) { throw null; } + public static int HashData(System.ReadOnlySpan key, System.IO.Stream source, System.Span destination) { throw null; } + public static byte[] HashData(System.ReadOnlySpan key, System.ReadOnlySpan source) { throw null; } + public static int HashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(byte[] key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + protected override byte[] HashFinal() { throw null; } + public override void Initialize() { } + public static bool TryHashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { throw null; } + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) { throw null; } + } + public partial class HMACSHA3_512 : System.Security.Cryptography.HMAC + { + public const int HashSizeInBits = 512; + public const int HashSizeInBytes = 64; + public HMACSHA3_512() { } + public HMACSHA3_512(byte[] key) { } + public static bool IsSupported { get { throw null; } } + public override byte[] Key { get { throw null; } set { } } + protected override void Dispose(bool disposing) { } + protected override void HashCore(byte[] rgb, int ib, int cb) { } + protected override void HashCore(System.ReadOnlySpan source) { } + public static byte[] HashData(byte[] key, byte[] source) { throw null; } + public static byte[] HashData(byte[] key, System.IO.Stream source) { throw null; } + public static byte[] HashData(System.ReadOnlySpan key, System.IO.Stream source) { throw null; } + public static int HashData(System.ReadOnlySpan key, System.IO.Stream source, System.Span destination) { throw null; } + public static byte[] HashData(System.ReadOnlySpan key, System.ReadOnlySpan source) { throw null; } + public static int HashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(byte[] key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Memory destination, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static System.Threading.Tasks.ValueTask HashDataAsync(System.ReadOnlyMemory key, System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + protected override byte[] HashFinal() { throw null; } + public override void Initialize() { } + public static bool TryHashData(System.ReadOnlySpan key, System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { throw null; } + protected override bool TryHashFinal(System.Span destination, out int bytesWritten) { throw null; } + } public partial class HMACSHA512 : System.Security.Cryptography.HMAC { public const int HashSizeInBits = 512; @@ -2006,6 +2084,9 @@ internal RSAEncryptionPadding() { } public static System.Security.Cryptography.RSAEncryptionPadding OaepSHA1 { get { throw null; } } public static System.Security.Cryptography.RSAEncryptionPadding OaepSHA256 { get { throw null; } } public static System.Security.Cryptography.RSAEncryptionPadding OaepSHA384 { get { throw null; } } + public static System.Security.Cryptography.RSAEncryptionPadding OaepSHA3_256 { get { throw null; } } + public static System.Security.Cryptography.RSAEncryptionPadding OaepSHA3_384 { get { throw null; } } + public static System.Security.Cryptography.RSAEncryptionPadding OaepSHA3_512 { get { throw null; } } public static System.Security.Cryptography.RSAEncryptionPadding OaepSHA512 { get { throw null; } } public static System.Security.Cryptography.RSAEncryptionPadding Pkcs1 { get { throw null; } } public static System.Security.Cryptography.RSAEncryptionPadding CreateOaep(System.Security.Cryptography.HashAlgorithmName hashAlgorithm) { throw null; } @@ -2292,6 +2373,54 @@ protected sealed override void HashCore(System.ReadOnlySpan source) { } public sealed override void Initialize() { } protected sealed override bool TryHashFinal(System.Span destination, out int bytesWritten) { throw null; } } + public abstract partial class SHA3_256 : System.Security.Cryptography.HashAlgorithm + { + public const int HashSizeInBits = 256; + public const int HashSizeInBytes = 32; + protected SHA3_256() { } + public static bool IsSupported { get { throw null; } } + public static new System.Security.Cryptography.SHA3_256 Create() { throw null; } + public static byte[] HashData(byte[] source) { throw null; } + public static byte[] HashData(System.IO.Stream source) { throw null; } + public static int HashData(System.IO.Stream source, System.Span destination) { throw null; } + public static byte[] HashData(System.ReadOnlySpan source) { throw null; } + public static int HashData(System.ReadOnlySpan source, System.Span destination) { 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 static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static bool TryHashData(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { throw null; } + } + public abstract partial class SHA3_384 : System.Security.Cryptography.HashAlgorithm + { + public const int HashSizeInBits = 384; + public const int HashSizeInBytes = 48; + protected SHA3_384() { } + public static bool IsSupported { get { throw null; } } + public static new System.Security.Cryptography.SHA3_384 Create() { throw null; } + public static byte[] HashData(byte[] source) { throw null; } + public static byte[] HashData(System.IO.Stream source) { throw null; } + public static int HashData(System.IO.Stream source, System.Span destination) { throw null; } + public static byte[] HashData(System.ReadOnlySpan source) { throw null; } + public static int HashData(System.ReadOnlySpan source, System.Span destination) { 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 static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static bool TryHashData(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { throw null; } + } + public abstract partial class SHA3_512 : System.Security.Cryptography.HashAlgorithm + { + public const int HashSizeInBits = 512; + public const int HashSizeInBytes = 64; + protected SHA3_512() { } + public static bool IsSupported { get { throw null; } } + public static new System.Security.Cryptography.SHA3_512 Create() { throw null; } + public static byte[] HashData(byte[] source) { throw null; } + public static byte[] HashData(System.IO.Stream source) { throw null; } + public static int HashData(System.IO.Stream source, System.Span destination) { throw null; } + public static byte[] HashData(System.ReadOnlySpan source) { throw null; } + public static int HashData(System.ReadOnlySpan source, System.Span destination) { 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 static System.Threading.Tasks.ValueTask HashDataAsync(System.IO.Stream source, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public static bool TryHashData(System.ReadOnlySpan source, System.Span destination, out int bytesWritten) { throw null; } + } public abstract partial class SHA512 : System.Security.Cryptography.HashAlgorithm { public const int HashSizeInBits = 512; 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 197dba5072bf5d..e572f791bf1b67 100644 --- a/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj +++ b/src/libraries/System.Security.Cryptography/src/System.Security.Cryptography.csproj @@ -352,6 +352,9 @@ + + + @@ -412,6 +415,9 @@ + + + diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.Unix.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.Unix.cs index 831b76f1f07a14..b11ecc91e4c62a 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.Unix.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/CapiHelper.Unix.cs @@ -37,6 +37,7 @@ internal static HashAlgorithmName NameOrOidToHashAlgorithmName(string? nameOrOid /// private static HashAlgorithmName AlgorithmToHashAlgorithmName(HashAlgorithm hashAlgorithm) { + // CAPI CSP doesn't support SHA-3, so don't add it here. return hashAlgorithm switch { SHA256 => HashAlgorithmName.SHA256, @@ -50,6 +51,7 @@ private static HashAlgorithmName AlgorithmToHashAlgorithmName(HashAlgorithm hash private static HashAlgorithmName OidToHashAlgorithmName(string oid) { + // CAPI CSP doesn't support SHA-3, so don't add it here. return oid switch { Oids.Sha256 => HashAlgorithmName.SHA256, @@ -63,6 +65,7 @@ private static HashAlgorithmName OidToHashAlgorithmName(string oid) private static HashAlgorithmName HashAlgorithmTypeToHashAlgorithmName(Type hashAlgType) { + // CAPI CSP doesn't support SHA-3, so don't add it here. if (typeof(SHA1).IsAssignableFrom(hashAlgType)) return HashAlgorithmName.SHA1; if (typeof(SHA256).IsAssignableFrom(hashAlgType)) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HKDF.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HKDF.cs index abb85e9a972e8c..1de6138cc1ec92 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HKDF.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HKDF.cs @@ -286,6 +286,18 @@ private static int HashLength(HashAlgorithmName hashAlgorithmName) { return HMACSHA512.HashSizeInBytes; } + else if (hashAlgorithmName == HashAlgorithmName.SHA3_256) + { + return HMACSHA3_256.HashSizeInBytes; + } + else if (hashAlgorithmName == HashAlgorithmName.SHA3_384) + { + return HMACSHA3_384.HashSizeInBytes; + } + else if (hashAlgorithmName == HashAlgorithmName.SHA3_512) + { + return HMACSHA3_512.HashSizeInBytes; + } else if (hashAlgorithmName == HashAlgorithmName.MD5) { return HMACMD5.HashSizeInBytes; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACCommon.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACCommon.cs index fec3c37cd3c620..25210f555df861 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACCommon.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACCommon.cs @@ -57,14 +57,37 @@ public void ChangeKey(byte[] key) if (key.Length > _blockSize && _blockSize > 0) { // Perform RFC 2104, section 2 key adjustment. - modifiedKey = _hashAlgorithmId switch + switch (_hashAlgorithmId) { - HashAlgorithmNames.SHA256 => SHA256.HashData(key), - HashAlgorithmNames.SHA384 => SHA384.HashData(key), - HashAlgorithmNames.SHA512 => SHA512.HashData(key), - HashAlgorithmNames.SHA1 => SHA1.HashData(key), - HashAlgorithmNames.MD5 when Helpers.HasMD5 => MD5.HashData(key), - _ => throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, _hashAlgorithmId)), + case HashAlgorithmNames.SHA256: + modifiedKey = SHA256.HashData(key); + break; + case HashAlgorithmNames.SHA384: + modifiedKey = SHA384.HashData(key); + break; + case HashAlgorithmNames.SHA512: + modifiedKey = SHA512.HashData(key); + break; + case HashAlgorithmNames.SHA3_256: + Debug.Assert(SHA3_256.IsSupported); + modifiedKey = SHA3_256.HashData(key); + break; + case HashAlgorithmNames.SHA3_384: + Debug.Assert(SHA3_384.IsSupported); + modifiedKey = SHA3_384.HashData(key); + break; + case HashAlgorithmNames.SHA3_512: + Debug.Assert(SHA3_512.IsSupported); + modifiedKey = SHA3_512.HashData(key); + break; + case HashAlgorithmNames.SHA1: + modifiedKey = SHA1.HashData(key); + break; + case HashAlgorithmNames.MD5 when Helpers.HasMD5: + modifiedKey = MD5.HashData(key); + break; + default: + throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, _hashAlgorithmId)); }; } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA3_256.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA3_256.cs new file mode 100644 index 00000000000000..d71c41bdf98540 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA3_256.cs @@ -0,0 +1,390 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Internal.Cryptography; +using System.Diagnostics; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Security.Cryptography +{ + /// + /// Computes a Hash-based Message Authentication Code (HMAC) by using the SHA3-256 hash function. + /// + public class HMACSHA3_256 : HMAC + { + private HMACCommon _hMacCommon; + internal const int BlockSize = 136; // FIPS 202 Table 3. + + /// + /// The hash size produced by the HMAC SHA3-256 algorithm, in bits. + /// + public const int HashSizeInBits = 256; + + /// + /// The hash size produced by the HMAC SHA3-256 algorithm, in bytes. + /// + public const int HashSizeInBytes = HashSizeInBits / 8; + + /// + /// Initializes a new instance of the class with a randomly generated key. + /// + /// + /// + /// is a type of keyed hash algorithm that is constructed from the SHA3-256 hash + /// function and used as a Hash-based Message Authentication Code (HMAC). The HMAC process mixes a secret key + /// with the message data, hashes the result with the hash function, mixes that hash value with the secret key + /// again, and then applies the hash function a second time. The output hash is 256 bits in length. + /// + /// + /// This constructor uses a 136-byte, randomly generated key. + /// + /// + public HMACSHA3_256() + : this(RandomNumberGenerator.GetBytes(BlockSize)) + { + } + + /// + /// Initializes a new instance of the class with the specified key data. + /// + /// + /// The secret key for . The key can be any length. + /// + /// + /// is . + /// + public HMACSHA3_256(byte[] key) + { + ArgumentNullException.ThrowIfNull(key); + CheckSha3Support(); + + this.HashName = HashAlgorithmNames.SHA3_256; + _hMacCommon = new HMACCommon(HashAlgorithmNames.SHA3_256, key, BlockSize); + base.Key = _hMacCommon.ActualKey!; + BlockSizeValue = BlockSize; + HashSizeValue = HashSizeInBits; + Debug.Assert(HashSizeValue == _hMacCommon.HashSizeInBits); + } + + /// + /// Gets a value that indicates whether the algorithm is supported on the current platform. + /// + /// + /// if the algorithm is supported; otherwise, . + /// + public static bool IsSupported { get; } = HashProviderDispenser.MacSupported(HashAlgorithmNames.SHA3_256); + + /// + public override byte[] Key + { + get + { + return base.Key; + } + set + { + ArgumentNullException.ThrowIfNull(value); + _hMacCommon.ChangeKey(value); + base.Key = _hMacCommon.ActualKey!; + } + } + + /// + protected override void HashCore(byte[] rgb, int ib, int cb) => + _hMacCommon.AppendHashData(rgb, ib, cb); + + /// + protected override void HashCore(ReadOnlySpan source) => + _hMacCommon.AppendHashData(source); + + /// + protected override byte[] HashFinal() => + _hMacCommon.FinalizeHashAndReset(); + + /// + protected override bool TryHashFinal(Span destination, out int bytesWritten) => + _hMacCommon.TryFinalizeHashAndReset(destination, out bytesWritten); + + /// + public override void Initialize() => _hMacCommon.Reset(); + + /// + /// Computes the HMAC of data using the SHA3-256 algorithm. + /// + /// The HMAC key. + /// The data to HMAC. + /// The HMAC of the data. + /// + /// or is . + /// + public static byte[] HashData(byte[] key, byte[] source) + { + ArgumentNullException.ThrowIfNull(key); + ArgumentNullException.ThrowIfNull(source); + + return HashData(new ReadOnlySpan(key), new ReadOnlySpan(source)); + } + + /// + /// Computes the HMAC of data using the SHA3-256 algorithm. + /// + /// The HMAC key. + /// The data to HMAC. + /// The HMAC of the data. + public static byte[] HashData(ReadOnlySpan key, ReadOnlySpan source) + { + byte[] buffer = new byte[HashSizeInBytes]; + + int written = HashData(key, source, buffer.AsSpan()); + Debug.Assert(written == buffer.Length); + + return buffer; + } + + /// + /// Computes the HMAC of data using the SHA3-256 algorithm. + /// + /// The HMAC key. + /// The data to HMAC. + /// The buffer to receive the HMAC value. + /// The total number of bytes written to . + /// + /// The buffer in is too small to hold the calculated hash + /// size. The SHA3-256 algorithm always produces a 256-bit HMAC, or 32 bytes. + /// + public static int HashData(ReadOnlySpan key, ReadOnlySpan source, Span destination) + { + if (!TryHashData(key, source, destination, out int bytesWritten)) + { + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + } + + return bytesWritten; + } + + /// + /// Attempts to compute the HMAC of data using the SHA3-256 algorithm. + /// + /// The HMAC key. + /// The data to HMAC. + /// The buffer to receive the HMAC value. + /// + /// When this method returns, the total number of bytes written into . + /// + /// + /// if is too small to hold the + /// calculated hash, otherwise. + /// + public static bool TryHashData(ReadOnlySpan key, ReadOnlySpan source, Span destination, out int bytesWritten) + { + CheckSha3Support(); + + if (destination.Length < HashSizeInBytes) + { + bytesWritten = 0; + return false; + } + + bytesWritten = HashProviderDispenser.OneShotHashProvider.MacData(HashAlgorithmNames.SHA3_256, key, source, destination); + Debug.Assert(bytesWritten == HashSizeInBytes); + + return true; + } + + /// + /// Computes the HMAC of a stream using the SHA3-256 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The buffer to receive the HMAC value. + /// The total number of bytes written to . + /// + /// is . + /// + /// + /// + /// The buffer in is too small to hold the calculated HMAC + /// size. The SHA3-256 algorithm always produces a 256-bit HMAC, or 32 bytes. + /// + /// -or- + /// + /// does not support reading. + /// + /// + public static int HashData(ReadOnlySpan key, Stream source, Span destination) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HmacStream(HashAlgorithmNames.SHA3_256, key, source, destination); + } + + /// + /// Computes the HMAC of a stream using the SHA3-256 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The HMAC of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(ReadOnlySpan key, Stream source) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HmacStream(HashAlgorithmNames.SHA3_256, HashSizeInBytes, key, source); + } + + /// + /// Computes the HMAC of a stream using the SHA3-256 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The HMAC of the data. + /// + /// or is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(byte[] key, Stream source) + { + ArgumentNullException.ThrowIfNull(key); + + return HashData(new ReadOnlySpan(key), source); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA3-256 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The HMAC of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(ReadOnlyMemory key, Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HmacStreamAsync(HashAlgorithmNames.SHA3_256, key.Span, source, cancellationToken); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA3-256 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The HMAC of the data. + /// + /// or is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(byte[] key, Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(key); + + return HashDataAsync(new ReadOnlyMemory(key), source, cancellationToken); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA3-256 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The buffer to receive the HMAC value. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The total number of bytes written to . + /// + /// is . + /// + /// + /// + /// The buffer in is too small to hold the calculated hash + /// size. The SHA3-256 algorithm always produces a 256-bit hash, or 32 bytes. + /// + /// -or- + /// + /// does not support reading. + /// + /// + public static ValueTask HashDataAsync( + ReadOnlyMemory key, + Stream source, + Memory destination, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HmacStreamAsync( + HashAlgorithmNames.SHA3_256, + key.Span, + source, + destination, + cancellationToken); + } + + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + HMACCommon hMacCommon = _hMacCommon; + if (hMacCommon != null) + { + _hMacCommon = null!; + hMacCommon.Dispose(disposing); + } + } + base.Dispose(disposing); + } + + private static void CheckSha3Support() + { + if (!IsSupported) + throw new PlatformNotSupportedException(); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA3_384.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA3_384.cs new file mode 100644 index 00000000000000..3e7497443098df --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA3_384.cs @@ -0,0 +1,390 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Internal.Cryptography; +using System.Diagnostics; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Security.Cryptography +{ + /// + /// Computes a Hash-based Message Authentication Code (HMAC) by using the SHA3-384 hash function. + /// + public class HMACSHA3_384 : HMAC + { + private HMACCommon _hMacCommon; + internal const int BlockSize = 104; // FIPS 202 Table 3. + + /// + /// The hash size produced by the HMAC SHA3-384 algorithm, in bits. + /// + public const int HashSizeInBits = 384; + + /// + /// The hash size produced by the HMAC SHA3-384 algorithm, in bytes. + /// + public const int HashSizeInBytes = HashSizeInBits / 8; + + /// + /// Initializes a new instance of the class with a randomly generated key. + /// + /// + /// + /// is a type of keyed hash algorithm that is constructed from the SHA3-384 hash + /// function and used as a Hash-based Message Authentication Code (HMAC). The HMAC process mixes a secret key + /// with the message data, hashes the result with the hash function, mixes that hash value with the secret key + /// again, and then applies the hash function a second time. The output hash is 384 bits in length. + /// + /// + /// This constructor uses a 104-byte, randomly generated key. + /// + /// + public HMACSHA3_384() + : this(RandomNumberGenerator.GetBytes(BlockSize)) + { + } + + /// + /// Initializes a new instance of the class with the specified key data. + /// + /// + /// The secret key for . The key can be any length. + /// + /// + /// is . + /// + public HMACSHA3_384(byte[] key) + { + ArgumentNullException.ThrowIfNull(key); + CheckSha3Support(); + + this.HashName = HashAlgorithmNames.SHA3_384; + _hMacCommon = new HMACCommon(HashAlgorithmNames.SHA3_384, key, BlockSize); + base.Key = _hMacCommon.ActualKey!; + BlockSizeValue = BlockSize; + HashSizeValue = HashSizeInBits; + Debug.Assert(HashSizeValue == _hMacCommon.HashSizeInBits); + } + + /// + /// Gets a value that indicates whether the algorithm is supported on the current platform. + /// + /// + /// if the algorithm is supported; otherwise, . + /// + public static bool IsSupported { get; } = HashProviderDispenser.MacSupported(HashAlgorithmNames.SHA3_384); + + /// + public override byte[] Key + { + get + { + return base.Key; + } + set + { + ArgumentNullException.ThrowIfNull(value); + _hMacCommon.ChangeKey(value); + base.Key = _hMacCommon.ActualKey!; + } + } + + /// + protected override void HashCore(byte[] rgb, int ib, int cb) => + _hMacCommon.AppendHashData(rgb, ib, cb); + + /// + protected override void HashCore(ReadOnlySpan source) => + _hMacCommon.AppendHashData(source); + + /// + protected override byte[] HashFinal() => + _hMacCommon.FinalizeHashAndReset(); + + /// + protected override bool TryHashFinal(Span destination, out int bytesWritten) => + _hMacCommon.TryFinalizeHashAndReset(destination, out bytesWritten); + + /// + public override void Initialize() => _hMacCommon.Reset(); + + /// + /// Computes the HMAC of data using the SHA3-384 algorithm. + /// + /// The HMAC key. + /// The data to HMAC. + /// The HMAC of the data. + /// + /// or is . + /// + public static byte[] HashData(byte[] key, byte[] source) + { + ArgumentNullException.ThrowIfNull(key); + ArgumentNullException.ThrowIfNull(source); + + return HashData(new ReadOnlySpan(key), new ReadOnlySpan(source)); + } + + /// + /// Computes the HMAC of data using the SHA3-384 algorithm. + /// + /// The HMAC key. + /// The data to HMAC. + /// The HMAC of the data. + public static byte[] HashData(ReadOnlySpan key, ReadOnlySpan source) + { + byte[] buffer = new byte[HashSizeInBytes]; + + int written = HashData(key, source, buffer.AsSpan()); + Debug.Assert(written == buffer.Length); + + return buffer; + } + + /// + /// Computes the HMAC of data using the SHA3-384 algorithm. + /// + /// The HMAC key. + /// The data to HMAC. + /// The buffer to receive the HMAC value. + /// The total number of bytes written to . + /// + /// The buffer in is too small to hold the calculated hash + /// size. The SHA3-384 algorithm always produces a 384-bit HMAC, or 48 bytes. + /// + public static int HashData(ReadOnlySpan key, ReadOnlySpan source, Span destination) + { + if (!TryHashData(key, source, destination, out int bytesWritten)) + { + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + } + + return bytesWritten; + } + + /// + /// Attempts to compute the HMAC of data using the SHA3-384 algorithm. + /// + /// The HMAC key. + /// The data to HMAC. + /// The buffer to receive the HMAC value. + /// + /// When this method returns, the total number of bytes written into . + /// + /// + /// if is too small to hold the + /// calculated hash, otherwise. + /// + public static bool TryHashData(ReadOnlySpan key, ReadOnlySpan source, Span destination, out int bytesWritten) + { + CheckSha3Support(); + + if (destination.Length < HashSizeInBytes) + { + bytesWritten = 0; + return false; + } + + bytesWritten = HashProviderDispenser.OneShotHashProvider.MacData(HashAlgorithmNames.SHA3_384, key, source, destination); + Debug.Assert(bytesWritten == HashSizeInBytes); + + return true; + } + + /// + /// Computes the HMAC of a stream using the SHA3-384 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The buffer to receive the HMAC value. + /// The total number of bytes written to . + /// + /// is . + /// + /// + /// + /// The buffer in is too small to hold the calculated HMAC + /// size. The SHA3-384 algorithm always produces a 384-bit HMAC, or 48 bytes. + /// + /// -or- + /// + /// does not support reading. + /// + /// + public static int HashData(ReadOnlySpan key, Stream source, Span destination) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HmacStream(HashAlgorithmNames.SHA3_384, key, source, destination); + } + + /// + /// Computes the HMAC of a stream using the SHA3-384 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The HMAC of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(ReadOnlySpan key, Stream source) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HmacStream(HashAlgorithmNames.SHA3_384, HashSizeInBytes, key, source); + } + + /// + /// Computes the HMAC of a stream using the SHA3-384 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The HMAC of the data. + /// + /// or is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(byte[] key, Stream source) + { + ArgumentNullException.ThrowIfNull(key); + + return HashData(new ReadOnlySpan(key), source); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA3-384 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The HMAC of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(ReadOnlyMemory key, Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HmacStreamAsync(HashAlgorithmNames.SHA3_384, key.Span, source, cancellationToken); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA3-384 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The HMAC of the data. + /// + /// or is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(byte[] key, Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(key); + + return HashDataAsync(new ReadOnlyMemory(key), source, cancellationToken); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA3-384 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The buffer to receive the HMAC value. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The total number of bytes written to . + /// + /// is . + /// + /// + /// + /// The buffer in is too small to hold the calculated hash + /// size. The SHA3-384 algorithm always produces a 384-bit hash, or 48 bytes. + /// + /// -or- + /// + /// does not support reading. + /// + /// + public static ValueTask HashDataAsync( + ReadOnlyMemory key, + Stream source, + Memory destination, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HmacStreamAsync( + HashAlgorithmNames.SHA3_384, + key.Span, + source, + destination, + cancellationToken); + } + + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + HMACCommon hMacCommon = _hMacCommon; + if (hMacCommon != null) + { + _hMacCommon = null!; + hMacCommon.Dispose(disposing); + } + } + base.Dispose(disposing); + } + + private static void CheckSha3Support() + { + if (!IsSupported) + throw new PlatformNotSupportedException(); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA3_512.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA3_512.cs new file mode 100644 index 00000000000000..62a6bb4f174072 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HMACSHA3_512.cs @@ -0,0 +1,390 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Internal.Cryptography; +using System.Diagnostics; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Security.Cryptography +{ + /// + /// Computes a Hash-based Message Authentication Code (HMAC) by using the SHA3-512 hash function. + /// + public class HMACSHA3_512 : HMAC + { + private HMACCommon _hMacCommon; + internal const int BlockSize = 72; // FIPS 202 Table 3. + + /// + /// The hash size produced by the HMAC SHA3-512 algorithm, in bits. + /// + public const int HashSizeInBits = 512; + + /// + /// The hash size produced by the HMAC SHA3-512 algorithm, in bytes. + /// + public const int HashSizeInBytes = HashSizeInBits / 8; + + /// + /// Initializes a new instance of the class with a randomly generated key. + /// + /// + /// + /// is a type of keyed hash algorithm that is constructed from the SHA3-512 hash + /// function and used as a Hash-based Message Authentication Code (HMAC). The HMAC process mixes a secret key + /// with the message data, hashes the result with the hash function, mixes that hash value with the secret key + /// again, and then applies the hash function a second time. The output hash is 512 bits in length. + /// + /// + /// This constructor uses a 72-byte, randomly generated key. + /// + /// + public HMACSHA3_512() + : this(RandomNumberGenerator.GetBytes(BlockSize)) + { + } + + /// + /// Initializes a new instance of the class with the specified key data. + /// + /// + /// The secret key for . The key can be any length. + /// + /// + /// is . + /// + public HMACSHA3_512(byte[] key) + { + ArgumentNullException.ThrowIfNull(key); + CheckSha3Support(); + + this.HashName = HashAlgorithmNames.SHA3_512; + _hMacCommon = new HMACCommon(HashAlgorithmNames.SHA3_512, key, BlockSize); + base.Key = _hMacCommon.ActualKey!; + BlockSizeValue = BlockSize; + HashSizeValue = HashSizeInBits; + Debug.Assert(HashSizeValue == _hMacCommon.HashSizeInBits); + } + + /// + /// Gets a value that indicates whether the algorithm is supported on the current platform. + /// + /// + /// if the algorithm is supported; otherwise, . + /// + public static bool IsSupported { get; } = HashProviderDispenser.MacSupported(HashAlgorithmNames.SHA3_512); + + /// + public override byte[] Key + { + get + { + return base.Key; + } + set + { + ArgumentNullException.ThrowIfNull(value); + _hMacCommon.ChangeKey(value); + base.Key = _hMacCommon.ActualKey!; + } + } + + /// + protected override void HashCore(byte[] rgb, int ib, int cb) => + _hMacCommon.AppendHashData(rgb, ib, cb); + + /// + protected override void HashCore(ReadOnlySpan source) => + _hMacCommon.AppendHashData(source); + + /// + protected override byte[] HashFinal() => + _hMacCommon.FinalizeHashAndReset(); + + /// + protected override bool TryHashFinal(Span destination, out int bytesWritten) => + _hMacCommon.TryFinalizeHashAndReset(destination, out bytesWritten); + + /// + public override void Initialize() => _hMacCommon.Reset(); + + /// + /// Computes the HMAC of data using the SHA3-512 algorithm. + /// + /// The HMAC key. + /// The data to HMAC. + /// The HMAC of the data. + /// + /// or is . + /// + public static byte[] HashData(byte[] key, byte[] source) + { + ArgumentNullException.ThrowIfNull(key); + ArgumentNullException.ThrowIfNull(source); + + return HashData(new ReadOnlySpan(key), new ReadOnlySpan(source)); + } + + /// + /// Computes the HMAC of data using the SHA3-512 algorithm. + /// + /// The HMAC key. + /// The data to HMAC. + /// The HMAC of the data. + public static byte[] HashData(ReadOnlySpan key, ReadOnlySpan source) + { + byte[] buffer = new byte[HashSizeInBytes]; + + int written = HashData(key, source, buffer.AsSpan()); + Debug.Assert(written == buffer.Length); + + return buffer; + } + + /// + /// Computes the HMAC of data using the SHA3-512 algorithm. + /// + /// The HMAC key. + /// The data to HMAC. + /// The buffer to receive the HMAC value. + /// The total number of bytes written to . + /// + /// The buffer in is too small to hold the calculated hash + /// size. The SHA3-512 algorithm always produces a 512-bit HMAC, or 64 bytes. + /// + public static int HashData(ReadOnlySpan key, ReadOnlySpan source, Span destination) + { + if (!TryHashData(key, source, destination, out int bytesWritten)) + { + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + } + + return bytesWritten; + } + + /// + /// Attempts to compute the HMAC of data using the SHA3-512 algorithm. + /// + /// The HMAC key. + /// The data to HMAC. + /// The buffer to receive the HMAC value. + /// + /// When this method returns, the total number of bytes written into . + /// + /// + /// if is too small to hold the + /// calculated hash, otherwise. + /// + public static bool TryHashData(ReadOnlySpan key, ReadOnlySpan source, Span destination, out int bytesWritten) + { + CheckSha3Support(); + + if (destination.Length < HashSizeInBytes) + { + bytesWritten = 0; + return false; + } + + bytesWritten = HashProviderDispenser.OneShotHashProvider.MacData(HashAlgorithmNames.SHA3_512, key, source, destination); + Debug.Assert(bytesWritten == HashSizeInBytes); + + return true; + } + + /// + /// Computes the HMAC of a stream using the SHA3-512 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The buffer to receive the HMAC value. + /// The total number of bytes written to . + /// + /// is . + /// + /// + /// + /// The buffer in is too small to hold the calculated HMAC + /// size. The SHA3-512 algorithm always produces a 512-bit HMAC, or 64 bytes. + /// + /// -or- + /// + /// does not support reading. + /// + /// + public static int HashData(ReadOnlySpan key, Stream source, Span destination) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HmacStream(HashAlgorithmNames.SHA3_512, key, source, destination); + } + + /// + /// Computes the HMAC of a stream using the SHA3-512 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The HMAC of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(ReadOnlySpan key, Stream source) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HmacStream(HashAlgorithmNames.SHA3_512, HashSizeInBytes, key, source); + } + + /// + /// Computes the HMAC of a stream using the SHA3-512 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The HMAC of the data. + /// + /// or is . + /// + /// + /// does not support reading. + /// + public static byte[] HashData(byte[] key, Stream source) + { + ArgumentNullException.ThrowIfNull(key); + + return HashData(new ReadOnlySpan(key), source); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA3-512 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The HMAC of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(ReadOnlyMemory key, Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HmacStreamAsync(HashAlgorithmNames.SHA3_512, key.Span, source, cancellationToken); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA3-512 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The HMAC of the data. + /// + /// or is . + /// + /// + /// does not support reading. + /// + public static ValueTask HashDataAsync(byte[] key, Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(key); + + return HashDataAsync(new ReadOnlyMemory(key), source, cancellationToken); + } + + /// + /// Asynchronously computes the HMAC of a stream using the SHA3-512 algorithm. + /// + /// The HMAC key. + /// The stream to HMAC. + /// The buffer to receive the HMAC value. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The total number of bytes written to . + /// + /// is . + /// + /// + /// + /// The buffer in is too small to hold the calculated hash + /// size. The SHA3-512 algorithm always produces a 512-bit hash, or 64 bytes. + /// + /// -or- + /// + /// does not support reading. + /// + /// + public static ValueTask HashDataAsync( + ReadOnlyMemory key, + Stream source, + Memory destination, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HmacStreamAsync( + HashAlgorithmNames.SHA3_512, + key.Span, + source, + destination, + cancellationToken); + } + + /// + protected override void Dispose(bool disposing) + { + if (disposing) + { + HMACCommon hMacCommon = _hMacCommon; + if (hMacCommon != null) + { + _hMacCommon = null!; + hMacCommon.Dispose(disposing); + } + } + base.Dispose(disposing); + } + + private static void CheckSha3Support() + { + if (!IsSupported) + throw new PlatformNotSupportedException(); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashAlgorithmName.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashAlgorithmName.cs index f7df0f24280251..c2e444b63a352a 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashAlgorithmName.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashAlgorithmName.cs @@ -52,6 +52,21 @@ namespace System.Security.Cryptography /// public static HashAlgorithmName SHA512 { get { return new HashAlgorithmName("SHA512"); } } + /// + /// Gets a representing "SHA3-256" + /// + public static HashAlgorithmName SHA3_256 => new HashAlgorithmName("SHA3-256"); + + /// + /// Gets a representing "SHA3-384" + /// + public static HashAlgorithmName SHA3_384 => new HashAlgorithmName("SHA3-384"); + + /// + /// Gets a representing "SHA3-512" + /// + public static HashAlgorithmName SHA3_512 => new HashAlgorithmName("SHA3-512"); + private readonly string? _name; /// @@ -142,6 +157,15 @@ public static bool TryFromOid(string oidValue, out HashAlgorithmName value) case Oids.Sha512: value = SHA512; return true; + case Oids.Sha3_256: + value = SHA3_256; + return true; + case Oids.Sha3_384: + value = SHA3_384; + return true; + case Oids.Sha3_512: + value = SHA3_512; + return true; default: value = default; return false; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashAlgorithmNames.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashAlgorithmNames.cs index 1b8f225ce4b7a1..00cfa2636a0170 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashAlgorithmNames.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashAlgorithmNames.cs @@ -14,6 +14,10 @@ internal static partial class HashAlgorithmNames public const string SHA384 = "SHA384"; public const string SHA512 = "SHA512"; + public const string SHA3_256 = "SHA3-256"; + public const string SHA3_384 = "SHA3-384"; + public const string SHA3_512 = "SHA3-512"; + /// /// Map HashAlgorithm type to string; .NET Framework uses CryptoConfig functionality. /// 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 296cafef903597..58ed1b42610e61 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 @@ -21,6 +21,23 @@ public static HashProvider CreateMacProvider(string hashAlgorithmId, ReadOnlySpa return new AppleHmacProvider(hashAlgorithmId, key); } + internal static bool HashSupported(string hashAlgorithmId) + { + switch (hashAlgorithmId) + { + case HashAlgorithmNames.MD5: + case HashAlgorithmNames.SHA1: + case HashAlgorithmNames.SHA256: + case HashAlgorithmNames.SHA384: + case HashAlgorithmNames.SHA512: + return true; + default: + return false; + } + } + + internal static bool MacSupported(string hashAlgorithmId) => HashSupported(hashAlgorithmId); + internal static class OneShotHashProvider { public static unsafe int MacData( diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Browser.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Browser.cs index 8bae776c7ac933..eea8e204cdc589 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Browser.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Browser.cs @@ -5,6 +5,22 @@ namespace System.Security.Cryptography { internal static partial class HashProviderDispenser { + internal static bool HashSupported(string hashAlgorithmId) + { + switch (hashAlgorithmId) + { + case HashAlgorithmNames.SHA1: + case HashAlgorithmNames.SHA256: + case HashAlgorithmNames.SHA384: + case HashAlgorithmNames.SHA512: + return true; + default: + return false; + } + } + + internal static bool MacSupported(string hashAlgorithmId) => HashSupported(hashAlgorithmId); + public static HashProvider CreateHashProvider(string hashAlgorithmId) { switch (hashAlgorithmId) diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.OpenSsl.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.OpenSsl.cs index 32cdc7dd93b1cc..78b8cd632b4340 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.OpenSsl.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.OpenSsl.cs @@ -22,6 +22,13 @@ internal static HashProvider CreateMacProvider(string hashAlgorithmId, ReadOnlyS return new HmacHashProvider(hashAlgorithmId, key); } + internal static bool HashSupported(string hashAlgorithmId) + { + return Interop.Crypto.HashAlgorithmSupported(hashAlgorithmId); + } + + internal static bool MacSupported(string hashAlgorithmId) => HashSupported(hashAlgorithmId); + internal static class OneShotHashProvider { public static int MacData( diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Windows.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Windows.cs index e195a153393924..f6ae0f97eb2307 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Windows.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/HashProviderDispenser.Windows.cs @@ -27,6 +27,50 @@ public static HashProvider CreateMacProvider(string hashAlgorithmId, ReadOnlySpa return new HashProviderCng(hashAlgorithmId, key, isHmac: true); } + internal static bool HashSupported(string hashAlgorithmId) + { + switch (hashAlgorithmId) + { + // We know that MD5, SHA1, and SHA2 are supported on all platforms. Don't bother asking. + case HashAlgorithmNames.MD5: + case HashAlgorithmNames.SHA1: + case HashAlgorithmNames.SHA256: + case HashAlgorithmNames.SHA384: + case HashAlgorithmNames.SHA512: + return true; + case HashAlgorithmNames.SHA3_256: + case HashAlgorithmNames.SHA3_384: + case HashAlgorithmNames.SHA3_512: + return BCryptAlgorithmCache.IsBCryptAlgorithmSupported( + hashAlgorithmId, + BCryptOpenAlgorithmProviderFlags.None); + default: + return false; + } + } + + internal static bool MacSupported(string hashAlgorithmId) + { + switch (hashAlgorithmId) + { + // We know that MD5, SHA1, and SHA2 are supported on all platforms. Don't bother asking. + case HashAlgorithmNames.MD5: + case HashAlgorithmNames.SHA1: + case HashAlgorithmNames.SHA256: + case HashAlgorithmNames.SHA384: + case HashAlgorithmNames.SHA512: + return true; + case HashAlgorithmNames.SHA3_256: + case HashAlgorithmNames.SHA3_384: + case HashAlgorithmNames.SHA3_512: + return BCryptAlgorithmCache.IsBCryptAlgorithmSupported( + hashAlgorithmId, + BCryptOpenAlgorithmProviderFlags.BCRYPT_ALG_HANDLE_HMAC_FLAG); + default: + return false; + } + } + public static class OneShotHashProvider { public static unsafe int MacData( @@ -143,6 +187,27 @@ private static unsafe void HashDataUsingPseudoHandle( Interop.BCrypt.BCryptAlgPseudoHandle.BCRYPT_SHA512_ALG_HANDLE; digestSizeInBytes = SHA512.HashSizeInBytes; } + else if (hashAlgorithmId == HashAlgorithmNames.SHA3_256) + { + algHandle = isHmac ? + Interop.BCrypt.BCryptAlgPseudoHandle.BCRYPT_HMAC_SHA3_256_ALG_HANDLE : + Interop.BCrypt.BCryptAlgPseudoHandle.BCRYPT_SHA3_256_ALG_HANDLE; + digestSizeInBytes = SHA3_256.HashSizeInBytes; + } + else if (hashAlgorithmId == HashAlgorithmNames.SHA3_384) + { + algHandle = isHmac ? + Interop.BCrypt.BCryptAlgPseudoHandle.BCRYPT_HMAC_SHA3_384_ALG_HANDLE : + Interop.BCrypt.BCryptAlgPseudoHandle.BCRYPT_SHA3_384_ALG_HANDLE; + digestSizeInBytes = SHA3_384.HashSizeInBytes; + } + else if (hashAlgorithmId == HashAlgorithmNames.SHA3_512) + { + algHandle = isHmac ? + Interop.BCrypt.BCryptAlgPseudoHandle.BCRYPT_HMAC_SHA3_512_ALG_HANDLE : + Interop.BCrypt.BCryptAlgPseudoHandle.BCRYPT_SHA3_512_ALG_HANDLE; + digestSizeInBytes = SHA3_512.HashSizeInBytes; + } else { Debug.Fail("Unknown hash algorithm."); diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/IncrementalHash.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/IncrementalHash.cs index 904c72c1c28050..022476b0bd3cc7 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/IncrementalHash.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/IncrementalHash.cs @@ -308,6 +308,7 @@ public void Dispose() public static IncrementalHash CreateHash(HashAlgorithmName hashAlgorithm) { ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + CheckSha3Support(hashAlgorithm.Name); return new IncrementalHash(hashAlgorithm, HashProviderDispenser.CreateHashProvider(hashAlgorithm.Name)); } @@ -366,8 +367,28 @@ public static IncrementalHash CreateHMAC(HashAlgorithmName hashAlgorithm, byte[] public static IncrementalHash CreateHMAC(HashAlgorithmName hashAlgorithm, ReadOnlySpan key) { ArgumentException.ThrowIfNullOrEmpty(hashAlgorithm.Name, nameof(hashAlgorithm)); + CheckSha3Support(hashAlgorithm.Name); return new IncrementalHash(hashAlgorithm, new HMACCommon(hashAlgorithm.Name, key, -1)); } + + private static void CheckSha3Support(string hashAlgorithmName) + { + switch (hashAlgorithmName) + { + case HashAlgorithmNames.SHA3_256 when !SHA3_256.IsSupported: + Debug.Assert(!HMACSHA3_256.IsSupported); + throw new PlatformNotSupportedException(); + case HashAlgorithmNames.SHA3_384 when !SHA3_384.IsSupported: + Debug.Assert(!HMACSHA3_384.IsSupported); + throw new PlatformNotSupportedException(); + case HashAlgorithmNames.SHA3_512 when !SHA3_512.IsSupported: + Debug.Assert(!HMACSHA3_512.IsSupported); + throw new PlatformNotSupportedException(); + default: + // Other unknown algorithms will be handled separately as CryptographicExceptions. + break; + } + } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/OidLookup.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/OidLookup.cs index 18e9dc392070d4..0108cb3f13e330 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/OidLookup.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/OidLookup.cs @@ -206,7 +206,8 @@ static void AddEntry(string oid, string primaryFriendlyName, string[]? additiona AddEntry("1.3.133.16.840.63.0.2", "ECDH_STD_SHA1_KDF"); AddEntry("1.3.132.1.11.1", "ECDH_STD_SHA256_KDF"); AddEntry("1.3.132.1.11.2", "ECDH_STD_SHA384_KDF"); - AddEntry("1.2.840.10045.3.1.7", "ECDSA_P256", new[] { "nistP256", "secP256r1", "x962P256v1", "ECDH_P256" } ); +#pragma warning disable CA1861 // Avoid constant arrays as arguments. Loaded by static constructor + AddEntry("1.2.840.10045.3.1.7", "ECDSA_P256", new[] { "nistP256", "secP256r1", "x962P256v1", "ECDH_P256" }); AddEntry("1.3.132.0.34", "ECDSA_P384", new[] { "nistP384", "secP384r1", "ECDH_P384" }); AddEntry("1.3.132.0.35", "ECDSA_P521", new[] { "nistP521", "secP521r1", "ECDH_P521" }); AddEntry("1.2.840.113549.1.9.16.3.5", "ESDH"); @@ -236,6 +237,7 @@ static void AddEntry(string oid, string primaryFriendlyName, string[]? additiona AddEntry("1.2.840.113549.1.1.7", "RSAES_OAEP"); AddEntry("1.2.840.113549.1.1.10", "RSASSA-PSS"); AddEntry("2.5.4.8", "S", new[] { "ST" }); +#pragma warning restore CA1861 // Avoid constant arrays as arguments AddEntry("1.3.132.0.9", "secP160k1"); AddEntry("1.3.132.0.8", "secP160r1"); AddEntry("1.3.132.0.30", "secP160r2"); diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Pbkdf2Implementation.Windows.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Pbkdf2Implementation.Windows.cs index 6829cbf7b63571..d05af7124b3af5 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Pbkdf2Implementation.Windows.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Pbkdf2Implementation.Windows.cs @@ -97,6 +97,15 @@ private static unsafe void FillKeyDerivation( case HashAlgorithmNames.SHA512: hashBufferSize = SHA512.HashData(password, hashBuffer); break; + case HashAlgorithmNames.SHA3_256: + hashBufferSize = SHA3_256.HashData(password, hashBuffer); + break; + case HashAlgorithmNames.SHA3_384: + hashBufferSize = SHA3_384.HashData(password, hashBuffer); + break; + case HashAlgorithmNames.SHA3_512: + hashBufferSize = SHA3_512.HashData(password, hashBuffer); + break; default: Debug.Fail($"Unexpected hash algorithm '{hashAlgorithmName}'"); throw new CryptographicException(); @@ -259,7 +268,7 @@ private static unsafe void FillDeriveKeyPBKDF2( private static int GetHashBlockSize(string hashAlgorithmName) { - // Block sizes per NIST FIPS pub 180-4. + // Block sizes per NIST FIPS pub 180-4 and FIPS 202. switch (hashAlgorithmName) { case HashAlgorithmNames.SHA1: @@ -268,6 +277,12 @@ private static int GetHashBlockSize(string hashAlgorithmName) case HashAlgorithmNames.SHA384: case HashAlgorithmNames.SHA512: return 1024 / 8; + case HashAlgorithmNames.SHA3_256: + return HMACSHA3_256.BlockSize; + case HashAlgorithmNames.SHA3_384: + return HMACSHA3_384.BlockSize; + case HashAlgorithmNames.SHA3_512: + return HMACSHA3_512.BlockSize; default: Debug.Fail($"Unexpected hash algorithm '{hashAlgorithmName}'"); throw new CryptographicException(); diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACryptoServiceProvider.Unix.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACryptoServiceProvider.Unix.cs index e6977e2e67e83f..7789143feb5b82 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACryptoServiceProvider.Unix.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSACryptoServiceProvider.Unix.cs @@ -183,6 +183,8 @@ public override byte[] SignData(Stream data, HashAlgorithmName hashAlgorithm, RS throw PaddingModeNotSupported(); } + CheckSHA3HashAlgorithm(hashAlgorithm); + return _impl.SignData(data, hashAlgorithm, padding); } @@ -195,6 +197,8 @@ public override byte[] SignData(byte[] data, int offset, int count, HashAlgorith throw PaddingModeNotSupported(); } + CheckSHA3HashAlgorithm(hashAlgorithm); + return _impl.SignData(data, offset, count, hashAlgorithm, padding); } @@ -207,6 +211,8 @@ public override bool TrySignData(ReadOnlySpan data, Span destination throw PaddingModeNotSupported(); } + CheckSHA3HashAlgorithm(hashAlgorithm); + return _impl.TrySignData(data, destination, hashAlgorithm, padding, out bytesWritten); } @@ -228,6 +234,8 @@ public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RS throw PaddingModeNotSupported(); } + CheckSHA3HashAlgorithm(hashAlgorithm); + return _impl.SignHash(hash, hashAlgorithm, padding); } @@ -240,6 +248,8 @@ public override bool TrySignHash(ReadOnlySpan hash, Span destination throw PaddingModeNotSupported(); } + CheckSHA3HashAlgorithm(hashAlgorithm); + return _impl.TrySignHash(hash, destination, hashAlgorithm, padding, out bytesWritten); } @@ -268,6 +278,8 @@ public override bool VerifyData(byte[] data, int offset, int count, byte[] signa throw PaddingModeNotSupported(); } + CheckSHA3HashAlgorithm(hashAlgorithm); + return _impl.VerifyData(data, offset, count, signature, hashAlgorithm, padding); } @@ -280,6 +292,8 @@ public override bool VerifyData(ReadOnlySpan data, ReadOnlySpan sign throw PaddingModeNotSupported(); } + CheckSHA3HashAlgorithm(hashAlgorithm); + return _impl.VerifyData(data, signature, hashAlgorithm, padding); } @@ -300,6 +314,8 @@ public override bool VerifyHash(ReadOnlySpan hash, ReadOnlySpan sign throw PaddingModeNotSupported(); } + CheckSHA3HashAlgorithm(hashAlgorithm); + return _impl.VerifyHash(hash, signature, hashAlgorithm, padding); } @@ -345,5 +361,16 @@ private static bool IsPublic(byte[] keyBlob) return true; } + + private static void CheckSHA3HashAlgorithm(HashAlgorithmName hashAlgorithm) + { + if (hashAlgorithm == HashAlgorithmName.SHA3_256 || + hashAlgorithm == HashAlgorithmName.SHA3_384 || + hashAlgorithm == HashAlgorithmName.SHA3_512) + { + // Compat: Windows throws CryptographicException for SHA-3 HashAlgorithmName. So we will here, too. + throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name)); + } + } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSAEncryptionPadding.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSAEncryptionPadding.cs index c31f665ad40008..9a2feee6dac982 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSAEncryptionPadding.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/RSAEncryptionPadding.cs @@ -10,36 +10,45 @@ namespace System.Security.Cryptography /// public sealed class RSAEncryptionPadding : IEquatable { - private static readonly RSAEncryptionPadding s_pkcs1 = new RSAEncryptionPadding(RSAEncryptionPaddingMode.Pkcs1, default(HashAlgorithmName)); - private static readonly RSAEncryptionPadding s_oaepSHA1 = CreateOaep(HashAlgorithmName.SHA1); - private static readonly RSAEncryptionPadding s_oaepSHA256 = CreateOaep(HashAlgorithmName.SHA256); - private static readonly RSAEncryptionPadding s_oaepSHA384 = CreateOaep(HashAlgorithmName.SHA384); - private static readonly RSAEncryptionPadding s_oaepSHA512 = CreateOaep(HashAlgorithmName.SHA512); - /// /// mode. /// - public static RSAEncryptionPadding Pkcs1 { get { return s_pkcs1; } } + public static RSAEncryptionPadding Pkcs1 { get; } = new RSAEncryptionPadding(RSAEncryptionPaddingMode.Pkcs1, default); /// /// mode with SHA1 hash algorithm. /// - public static RSAEncryptionPadding OaepSHA1 { get { return s_oaepSHA1; } } + public static RSAEncryptionPadding OaepSHA1 { get; } = CreateOaep(HashAlgorithmName.SHA1); /// /// mode with SHA256 hash algorithm. /// - public static RSAEncryptionPadding OaepSHA256 { get { return s_oaepSHA256; } } + public static RSAEncryptionPadding OaepSHA256 { get; } = CreateOaep(HashAlgorithmName.SHA256); /// /// mode with SHA384 hash algorithm. /// - public static RSAEncryptionPadding OaepSHA384 { get { return s_oaepSHA384; } } + public static RSAEncryptionPadding OaepSHA384 { get; } = CreateOaep(HashAlgorithmName.SHA384); /// /// mode with SHA512 hash algorithm. /// - public static RSAEncryptionPadding OaepSHA512 { get { return s_oaepSHA512; } } + public static RSAEncryptionPadding OaepSHA512 { get; } = CreateOaep(HashAlgorithmName.SHA512); + + /// + /// mode with SHA3-256 hash algorithm. + /// + public static RSAEncryptionPadding OaepSHA3_256 { get; } = CreateOaep(HashAlgorithmName.SHA3_256); + + /// + /// mode with SHA3-384 hash algorithm. + /// + public static RSAEncryptionPadding OaepSHA3_384 { get; } = CreateOaep(HashAlgorithmName.SHA3_384); + + /// + /// mode with SHA3-512 hash algorithm. + /// + public static RSAEncryptionPadding OaepSHA3_512 { get; } = CreateOaep(HashAlgorithmName.SHA3_512); private readonly RSAEncryptionPaddingMode _mode; private readonly HashAlgorithmName _oaepHashAlgorithm; diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Rfc2898DeriveBytes.OneShot.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Rfc2898DeriveBytes.OneShot.cs index 88ca89094e3da0..a07718238a6d34 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Rfc2898DeriveBytes.OneShot.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Rfc2898DeriveBytes.OneShot.cs @@ -323,13 +323,29 @@ private static void ValidateHashAlgorithm(HashAlgorithmName hashAlgorithm) ArgumentException.ThrowIfNullOrEmpty(hashAlgorithmName, nameof(hashAlgorithm)); // MD5 intentionally left out. - if (hashAlgorithmName != HashAlgorithmName.SHA1.Name && - hashAlgorithmName != HashAlgorithmName.SHA256.Name && - hashAlgorithmName != HashAlgorithmName.SHA384.Name && - hashAlgorithmName != HashAlgorithmName.SHA512.Name) + if (hashAlgorithmName == HashAlgorithmName.SHA1.Name || + hashAlgorithmName == HashAlgorithmName.SHA256.Name || + hashAlgorithmName == HashAlgorithmName.SHA384.Name || + hashAlgorithmName == HashAlgorithmName.SHA512.Name) { - throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmName)); + return; + } + + if (hashAlgorithmName == HashAlgorithmName.SHA3_256.Name || + hashAlgorithmName == HashAlgorithmName.SHA3_384.Name || + hashAlgorithmName == HashAlgorithmName.SHA3_512.Name) + { + // All current platforms support HMAC-SHA3-256, 384, and 512 together, so we can simplify the check + // to just checking HMAC-SHA3-256 for the availability of 384 and 512, too. + if (HMACSHA3_256.IsSupported) + { + return; + } + + throw new PlatformNotSupportedException(); } + + throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmName)); } } } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Rfc2898DeriveBytes.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Rfc2898DeriveBytes.cs index 736fc089ee9041..4c1ee1acc8663f 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Rfc2898DeriveBytes.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/Rfc2898DeriveBytes.cs @@ -252,7 +252,10 @@ private IncrementalHash OpenHmac(ReadOnlySpan password) if (hashAlgorithm != HashAlgorithmName.SHA1 && hashAlgorithm != HashAlgorithmName.SHA256 && hashAlgorithm != HashAlgorithmName.SHA384 && - hashAlgorithm != HashAlgorithmName.SHA512) + hashAlgorithm != HashAlgorithmName.SHA512 && + hashAlgorithm != HashAlgorithmName.SHA3_256 && + hashAlgorithm != HashAlgorithmName.SHA3_384 && + hashAlgorithm != HashAlgorithmName.SHA3_512) { throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithm.Name)); } diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA3_256.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA3_256.cs new file mode 100644 index 00000000000000..659fa2d2926550 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA3_256.cs @@ -0,0 +1,324 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Internal.Cryptography; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Security.Cryptography +{ + /// + /// Computes the SHA3-256 hash for the input data. + /// + /// + /// This algorithm is specified by FIPS 202. + /// + public abstract class SHA3_256 : HashAlgorithm + { + /// + /// The hash size produced by the SHA3-256 algorithm, in bits. + /// + public const int HashSizeInBits = 256; + + /// + /// The hash size produced by the SHA3-256 algorithm, in bytes. + /// + public const int HashSizeInBytes = HashSizeInBits / 8; + + /// + /// Initializes a new instance of . + /// + protected SHA3_256() + { + HashSizeValue = HashSizeInBits; + } + + /// + /// Gets a value that indicates whether the algorithm is supported on the current platform. + /// + /// + /// if the algorithm is supported; otherwise, . + /// + public static bool IsSupported { get; } = HashProviderDispenser.HashSupported(HashAlgorithmNames.SHA3_256); + + /// + /// Creates an instance of the default implementation of . + /// + /// + /// A new instance of . + /// + /// + /// The platform does not support SHA3-256. + /// + public static new SHA3_256 Create() + { + CheckSha3Support(); + return new Implementation(); + } + + /// + /// Computes the hash of data using the SHA3-256 algorithm. + /// + /// The data to hash. + /// The hash of the data. + /// + /// is . + /// + /// + /// The platform does not support SHA3-256. + /// + public static byte[] HashData(byte[] source) + { + ArgumentNullException.ThrowIfNull(source); + + return HashData(new ReadOnlySpan(source)); + } + + /// + /// Computes the hash of data using the SHA3-256 algorithm. + /// + /// The data to hash. + /// The hash of the data. + /// + /// The platform does not support SHA3-256. + /// + public static byte[] HashData(ReadOnlySpan source) + { + byte[] buffer = new byte[HashSizeInBytes]; + + int written = HashData(source, buffer.AsSpan()); + Debug.Assert(written == buffer.Length); + + return buffer; + } + + /// + /// Computes the hash of data using the SHA3-256 algorithm. + /// + /// The data to hash. + /// The buffer to receive the hash value. + /// The total number of bytes written to . + /// + /// The buffer in is too small to hold the calculated hash + /// size. The SHA3-256 algorithm always produces a 256-bit hash, or 32 bytes. + /// + /// + /// The platform does not support SHA3-256. + /// + public static int HashData(ReadOnlySpan source, Span destination) + { + if (!TryHashData(source, destination, out int bytesWritten)) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + return bytesWritten; + } + + /// + /// Attempts to compute the hash of data using the SHA3-256 algorithm. + /// + /// The data to hash. + /// The buffer to receive the hash value. + /// + /// When this method returns, the total number of bytes written into . + /// + /// + /// if is too small to hold the + /// calculated hash, otherwise. + /// + /// + /// The platform does not support SHA3-256. + /// + public static bool TryHashData(ReadOnlySpan source, Span destination, out int bytesWritten) + { + CheckSha3Support(); + + if (destination.Length < HashSizeInBytes) + { + bytesWritten = 0; + return false; + } + + bytesWritten = HashProviderDispenser.OneShotHashProvider.HashData(HashAlgorithmNames.SHA3_256, source, destination); + Debug.Assert(bytesWritten == HashSizeInBytes); + + return true; + } + + /// + /// Computes the hash of a stream using the SHA3-256 algorithm. + /// + /// The stream to hash. + /// The buffer to receive the hash value. + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated hash + /// size. The SHA3-256 algorithm always produces a 256-bit hash, or 32 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ /// + /// The platform does not support SHA3-256. + /// + public static int HashData(Stream source, Span destination) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HashStream(HashAlgorithmNames.SHA3_256, source, destination); + } + + /// + /// Computes the hash of a stream using the SHA3-256 algorithm. + /// + /// The stream to hash. + /// The hash of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + /// + /// The platform does not support SHA3-256. + /// + public static byte[] HashData(Stream source) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HashStream(HashAlgorithmNames.SHA3_256, HashSizeInBytes, source); + } + + /// + /// Asynchronously computes the hash of a stream using the SHA3-256 algorithm. + /// + /// The stream to hash. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The hash of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + /// + /// The platform does not support SHA3-256. + /// + public static ValueTask HashDataAsync(Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HashStreamAsync(HashAlgorithmNames.SHA3_256, source, cancellationToken); + } + + /// + /// Asynchronously computes the hash of a stream using the SHA3-256 algorithm. + /// + /// The stream to hash. + /// The buffer to receive the hash value. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The total number of bytes written to . + /// + /// is . + /// + /// + ///

+ /// The buffer in is too small to hold the calculated hash + /// size. The SHA3-256 algorithm always produces a 256-bit hash, or 32 bytes. + ///

+ ///

-or-

+ ///

+ /// does not support reading. + ///

+ ///
+ /// + /// The platform does not support SHA3-256. + /// + public static ValueTask HashDataAsync( + Stream source, + Memory destination, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HashStreamAsync( + HashAlgorithmNames.SHA3_256, + source, + destination, + cancellationToken); + } + + private static void CheckSha3Support() + { + if (!IsSupported) + throw new PlatformNotSupportedException(); + } + + private sealed class Implementation : SHA3_256 + { + private readonly HashProvider _hashProvider; + + public Implementation() + { + _hashProvider = HashProviderDispenser.CreateHashProvider(HashAlgorithmNames.SHA3_256); + HashSizeValue = _hashProvider.HashSizeInBytes * 8; + } + + protected sealed override void HashCore(byte[] array, int ibStart, int cbSize) => + _hashProvider.AppendHashData(array, ibStart, cbSize); + + protected sealed override void HashCore(ReadOnlySpan source) => + _hashProvider.AppendHashData(source); + + protected sealed override byte[] HashFinal() => + _hashProvider.FinalizeHashAndReset(); + + protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => + _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); + + public sealed override void Initialize() => _hashProvider.Reset(); + + protected sealed override void Dispose(bool disposing) + { + _hashProvider.Dispose(disposing); + base.Dispose(disposing); + } + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA3_384.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA3_384.cs new file mode 100644 index 00000000000000..d74787d4698e93 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA3_384.cs @@ -0,0 +1,325 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Internal.Cryptography; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Security.Cryptography +{ + /// + /// Computes the SHA3-384 hash for the input data. + /// + /// + /// This algorithm is specified by FIPS 202. + /// + public abstract class SHA3_384 : HashAlgorithm + { + /// + /// The hash size produced by the SHA3-384 algorithm, in bits. + /// + public const int HashSizeInBits = 384; + + /// + /// The hash size produced by the SHA3-384 algorithm, in bytes. + /// + public const int HashSizeInBytes = HashSizeInBits / 8; + + /// + /// Initializes a new instance of . + /// + protected SHA3_384() + { + HashSizeValue = HashSizeInBits; + } + + /// + /// Gets a value that indicates whether the algorithm is supported on the current platform. + /// + /// + /// if the algorithm is supported; otherwise, . + /// + public static bool IsSupported { get; } = HashProviderDispenser.HashSupported(HashAlgorithmNames.SHA3_384); + + /// + /// Creates an instance of the default implementation of . + /// + /// + /// A new instance of . + /// + /// + /// The platform does not support SHA3-384. + /// + public static new SHA3_384 Create() + { + CheckSha3Support(); + return new Implementation(); + } + + /// + /// Computes the hash of data using the SHA3-384 algorithm. + /// + /// The data to hash. + /// The hash of the data. + /// + /// is . + /// + /// + /// The platform does not support SHA3-384. + /// + public static byte[] HashData(byte[] source) + { + ArgumentNullException.ThrowIfNull(source); + + return HashData(new ReadOnlySpan(source)); + } + + /// + /// Computes the hash of data using the SHA3-384 algorithm. + /// + /// The data to hash. + /// The hash of the data. + /// + /// The platform does not support SHA3-384. + /// + public static byte[] HashData(ReadOnlySpan source) + { + byte[] buffer = new byte[HashSizeInBytes]; + + int written = HashData(source, buffer.AsSpan()); + Debug.Assert(written == buffer.Length); + + return buffer; + } + + /// + /// Computes the hash of data using the SHA3-384 algorithm. + /// + /// The data to hash. + /// The buffer to receive the hash value. + /// The total number of bytes written to . + /// + /// The buffer in is too small to hold the calculated hash + /// size. The SHA3-384 algorithm always produces a 384-bit hash, or 48 bytes. + /// + /// + /// The platform does not support SHA3-384. + /// + public static int HashData(ReadOnlySpan source, Span destination) + { + if (!TryHashData(source, destination, out int bytesWritten)) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + return bytesWritten; + } + + + /// + /// Attempts to compute the hash of data using the SHA3-384 algorithm. + /// + /// The data to hash. + /// The buffer to receive the hash value. + /// + /// When this method returns, the total number of bytes written into . + /// + /// + /// if is too small to hold the + /// calculated hash, otherwise. + /// + /// + /// The platform does not support SHA3-384. + /// + public static bool TryHashData(ReadOnlySpan source, Span destination, out int bytesWritten) + { + CheckSha3Support(); + + if (destination.Length < HashSizeInBytes) + { + bytesWritten = 0; + return false; + } + + bytesWritten = HashProviderDispenser.OneShotHashProvider.HashData(HashAlgorithmNames.SHA3_384, source, destination); + Debug.Assert(bytesWritten == HashSizeInBytes); + + return true; + } + + /// + /// Computes the hash of a stream using the SHA3-384 algorithm. + /// + /// The stream to hash. + /// The buffer to receive the hash value. + /// The total number of bytes written to . + /// + /// is . + /// + /// + /// + /// The buffer in is too small to hold the calculated hash + /// size. The SHA3-384 algorithm always produces a 384-bit hash, or 48 bytes. + /// + /// -or- + /// + /// does not support reading. + /// + /// + /// + /// The platform does not support SHA3-384. + /// + public static int HashData(Stream source, Span destination) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HashStream(HashAlgorithmNames.SHA3_384, source, destination); + } + + /// + /// Computes the hash of a stream using the SHA3-384 algorithm. + /// + /// The stream to hash. + /// The hash of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + /// + /// The platform does not support SHA3-384. + /// + public static byte[] HashData(Stream source) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HashStream(HashAlgorithmNames.SHA3_384, HashSizeInBytes, source); + } + + /// + /// Asynchronously computes the hash of a stream using the SHA3-384 algorithm. + /// + /// The stream to hash. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The hash of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + /// + /// The platform does not support SHA3-384. + /// + public static ValueTask HashDataAsync(Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HashStreamAsync(HashAlgorithmNames.SHA3_384, source, cancellationToken); + } + + /// + /// Asynchronously computes the hash of a stream using the SHA3-384 algorithm. + /// + /// The stream to hash. + /// The buffer to receive the hash value. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The total number of bytes written to . + /// + /// is . + /// + /// + /// + /// The buffer in is too small to hold the calculated hash + /// size. The SHA3-384 algorithm always produces a 384-bit hash, or 48 bytes. + /// + /// -or- + /// + /// does not support reading. + /// + /// + /// + /// The platform does not support SHA3-384. + /// + public static ValueTask HashDataAsync( + Stream source, + Memory destination, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HashStreamAsync( + HashAlgorithmNames.SHA3_384, + source, + destination, + cancellationToken); + } + + private static void CheckSha3Support() + { + if (!IsSupported) + throw new PlatformNotSupportedException(); + } + + private sealed class Implementation : SHA3_384 + { + private readonly HashProvider _hashProvider; + + public Implementation() + { + _hashProvider = HashProviderDispenser.CreateHashProvider(HashAlgorithmNames.SHA3_384); + HashSizeValue = _hashProvider.HashSizeInBytes * 8; + } + + protected sealed override void HashCore(byte[] array, int ibStart, int cbSize) => + _hashProvider.AppendHashData(array, ibStart, cbSize); + + protected sealed override void HashCore(ReadOnlySpan source) => + _hashProvider.AppendHashData(source); + + protected sealed override byte[] HashFinal() => + _hashProvider.FinalizeHashAndReset(); + + protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => + _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); + + public sealed override void Initialize() => _hashProvider.Reset(); + + protected sealed override void Dispose(bool disposing) + { + _hashProvider.Dispose(disposing); + base.Dispose(disposing); + } + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA3_512.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA3_512.cs new file mode 100644 index 00000000000000..2c716453827a3c --- /dev/null +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SHA3_512.cs @@ -0,0 +1,324 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Internal.Cryptography; +using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace System.Security.Cryptography +{ + /// + /// Computes the SHA3-512 hash for the input data. + /// + /// + /// This algorithm is specified by FIPS 202. + /// + public abstract class SHA3_512 : HashAlgorithm + { + /// + /// The hash size produced by the SHA3-512 algorithm, in bits. + /// + public const int HashSizeInBits = 512; + + /// + /// The hash size produced by the SHA3-512 algorithm, in bytes. + /// + public const int HashSizeInBytes = HashSizeInBits / 8; + + /// + /// Initializes a new instance of . + /// + protected SHA3_512() + { + HashSizeValue = HashSizeInBits; + } + + /// + /// Gets a value that indicates whether the algorithm is supported on the current platform. + /// + /// + /// if the algorithm is supported; otherwise, . + /// + public static bool IsSupported { get; } = HashProviderDispenser.HashSupported(HashAlgorithmNames.SHA3_512); + + /// + /// Creates an instance of the default implementation of . + /// + /// + /// A new instance of . + /// + /// + /// The platform does not support SHA3-512. + /// + public static new SHA3_512 Create() + { + CheckSha3Support(); + return new Implementation(); + } + + /// + /// Computes the hash of data using the SHA3-512 algorithm. + /// + /// The data to hash. + /// The hash of the data. + /// + /// is . + /// + /// + /// The platform does not support SHA3-512. + /// + public static byte[] HashData(byte[] source) + { + ArgumentNullException.ThrowIfNull(source); + + return HashData(new ReadOnlySpan(source)); + } + + /// + /// Computes the hash of data using the SHA3-512 algorithm. + /// + /// The data to hash. + /// The hash of the data. + /// + /// The platform does not support SHA3-512. + /// + public static byte[] HashData(ReadOnlySpan source) + { + byte[] buffer = new byte[HashSizeInBytes]; + + int written = HashData(source, buffer.AsSpan()); + Debug.Assert(written == buffer.Length); + + return buffer; + } + + /// + /// Computes the hash of data using the SHA3-512 algorithm. + /// + /// The data to hash. + /// The buffer to receive the hash value. + /// The total number of bytes written to . + /// + /// The buffer in is too small to hold the calculated hash + /// size. The SHA3-512 algorithm always produces a 512-bit hash, or 64 bytes. + /// + /// + /// The platform does not support SHA3-512. + /// + public static int HashData(ReadOnlySpan source, Span destination) + { + if (!TryHashData(source, destination, out int bytesWritten)) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + return bytesWritten; + } + + /// + /// Attempts to compute the hash of data using the SHA3-512 algorithm. + /// + /// The data to hash. + /// The buffer to receive the hash value. + /// + /// When this method returns, the total number of bytes written into . + /// + /// + /// if is too small to hold the + /// calculated hash, otherwise. + /// + /// + /// The platform does not support SHA3-512. + /// + public static bool TryHashData(ReadOnlySpan source, Span destination, out int bytesWritten) + { + CheckSha3Support(); + + if (destination.Length < HashSizeInBytes) + { + bytesWritten = 0; + return false; + } + + bytesWritten = HashProviderDispenser.OneShotHashProvider.HashData(HashAlgorithmNames.SHA3_512, source, destination); + Debug.Assert(bytesWritten == HashSizeInBytes); + + return true; + } + + /// + /// Computes the hash of a stream using the SHA3-512 algorithm. + /// + /// The stream to hash. + /// The buffer to receive the hash value. + /// The total number of bytes written to . + /// + /// is . + /// + /// + /// + /// The buffer in is too small to hold the calculated hash + /// size. The SHA3-512 algorithm always produces a 512-bit hash, or 64 bytes. + /// + /// -or- + /// + /// does not support reading. + /// + /// + /// + /// The platform does not support SHA3-512. + /// + public static int HashData(Stream source, Span destination) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HashStream(HashAlgorithmNames.SHA3_512, source, destination); + } + + /// + /// Computes the hash of a stream using the SHA3-512 algorithm. + /// + /// The stream to hash. + /// The hash of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + /// + /// The platform does not support SHA3-512. + /// + public static byte[] HashData(Stream source) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HashStream(HashAlgorithmNames.SHA3_512, HashSizeInBytes, source); + } + + /// + /// Asynchronously computes the hash of a stream using the SHA3-512 algorithm. + /// + /// The stream to hash. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The hash of the data. + /// + /// is . + /// + /// + /// does not support reading. + /// + /// + /// The platform does not support SHA3-512. + /// + public static ValueTask HashDataAsync(Stream source, CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HashStreamAsync(HashAlgorithmNames.SHA3_512, source, cancellationToken); + } + + /// + /// Asynchronously computes the hash of a stream using the SHA3-512 algorithm. + /// + /// The stream to hash. + /// The buffer to receive the hash value. + /// + /// The token to monitor for cancellation requests. + /// The default value is . + /// + /// The total number of bytes written to . + /// + /// is . + /// + /// + /// + /// The buffer in is too small to hold the calculated hash + /// size. The SHA3-512 algorithm always produces a 512-bit hash, or 64 bytes. + /// + /// -or- + /// + /// does not support reading. + /// + /// + /// + /// The platform does not support SHA3-512. + /// + public static ValueTask HashDataAsync( + Stream source, + Memory destination, + CancellationToken cancellationToken = default) + { + ArgumentNullException.ThrowIfNull(source); + + if (destination.Length < HashSizeInBytes) + throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination)); + + if (!source.CanRead) + throw new ArgumentException(SR.Argument_StreamNotReadable, nameof(source)); + + CheckSha3Support(); + return LiteHashProvider.HashStreamAsync( + HashAlgorithmNames.SHA3_512, + source, + destination, + cancellationToken); + } + + private static void CheckSha3Support() + { + if (!IsSupported) + throw new PlatformNotSupportedException(); + } + + private sealed class Implementation : SHA3_512 + { + private readonly HashProvider _hashProvider; + + public Implementation() + { + _hashProvider = HashProviderDispenser.CreateHashProvider(HashAlgorithmNames.SHA3_512); + HashSizeValue = _hashProvider.HashSizeInBytes * 8; + } + + protected sealed override void HashCore(byte[] array, int ibStart, int cbSize) => + _hashProvider.AppendHashData(array, ibStart, cbSize); + + protected sealed override void HashCore(ReadOnlySpan source) => + _hashProvider.AppendHashData(source); + + protected sealed override byte[] HashFinal() => + _hashProvider.FinalizeHashAndReset(); + + protected sealed override bool TryHashFinal(Span destination, out int bytesWritten) => + _hashProvider.TryFinalizeHashAndReset(destination, out bytesWritten); + + public sealed override void Initialize() => _hashProvider.Reset(); + + protected sealed override void Dispose(bool disposing) + { + _hashProvider.Dispose(disposing); + base.Dispose(disposing); + } + } + } +} diff --git a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SP800108HmacCounterKdfImplementationCng.cs b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SP800108HmacCounterKdfImplementationCng.cs index 75025e598ffc08..77adda425ce3d6 100644 --- a/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SP800108HmacCounterKdfImplementationCng.cs +++ b/src/libraries/System.Security.Cryptography/src/System/Security/Cryptography/SP800108HmacCounterKdfImplementationCng.cs @@ -65,6 +65,12 @@ private static int HashOneShot(HashAlgorithmName hashAlgorithm, ReadOnlySpan true; + public bool SupportsSha3 => false; + private static bool IsValueOrFriendlyNameValid(string friendlyNameOrValue) { if (string.IsNullOrEmpty(friendlyNameOrValue)) diff --git a/src/libraries/System.Security.Cryptography/tests/DefaultECDiffieHellmanProvider.Unix.cs b/src/libraries/System.Security.Cryptography/tests/DefaultECDiffieHellmanProvider.Unix.cs index d00c95b27eaffa..162831d72ac696 100644 --- a/src/libraries/System.Security.Cryptography/tests/DefaultECDiffieHellmanProvider.Unix.cs +++ b/src/libraries/System.Security.Cryptography/tests/DefaultECDiffieHellmanProvider.Unix.cs @@ -36,6 +36,7 @@ public bool ExplicitCurvesSupported public bool CanDeriveNewPublicKey { get; } = !PlatformDetection.IsiOS && !PlatformDetection.IstvOS && !PlatformDetection.IsMacCatalyst; public bool SupportsRawDerivation => true; + public bool SupportsSha3 => PlatformDetection.SupportsSha3; private static bool IsValueOrFriendlyNameValid(string friendlyNameOrValue) { diff --git a/src/libraries/System.Security.Cryptography/tests/DefaultECDiffieHellmanProvider.Windows.cs b/src/libraries/System.Security.Cryptography/tests/DefaultECDiffieHellmanProvider.Windows.cs index 49f8ff15761e17..71471a532acdb3 100644 --- a/src/libraries/System.Security.Cryptography/tests/DefaultECDiffieHellmanProvider.Windows.cs +++ b/src/libraries/System.Security.Cryptography/tests/DefaultECDiffieHellmanProvider.Windows.cs @@ -24,6 +24,7 @@ public bool ExplicitCurvesSupported public bool CanDeriveNewPublicKey => true; public bool SupportsRawDerivation => PlatformDetection.IsWindows10OrLater; + public bool SupportsSha3 => PlatformDetection.SupportsSha3; private static bool NativeOidFriendlyNameExists(string oidFriendlyName) { diff --git a/src/libraries/System.Security.Cryptography/tests/DefaultRSAProvider.cs b/src/libraries/System.Security.Cryptography/tests/DefaultRSAProvider.cs index e39bc782bc04a4..c65b78ace1288e 100644 --- a/src/libraries/System.Security.Cryptography/tests/DefaultRSAProvider.cs +++ b/src/libraries/System.Security.Cryptography/tests/DefaultRSAProvider.cs @@ -47,6 +47,8 @@ public bool Supports384PrivateKey public bool SupportsSha2Oaep { get; } = true; public bool SupportsPss { get; } = true; + + public bool SupportsSha3 { get; } = SHA3_256.IsSupported; // If SHA3_256 is supported, assume 384 and 512 are, too. } public partial class RSAFactory diff --git a/src/libraries/System.Security.Cryptography/tests/HKDFTests.cs b/src/libraries/System.Security.Cryptography/tests/HKDFTests.cs index 059c60c42bbf90..6f58c00e80994c 100644 --- a/src/libraries/System.Security.Cryptography/tests/HKDFTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/HKDFTests.cs @@ -15,25 +15,25 @@ public abstract class HKDFTests protected abstract byte[] DeriveKey(HashAlgorithmName hash, byte[] ikm, int outputLength, byte[] salt, byte[] info); [Theory] - [MemberData(nameof(GetRfc5869TestCases))] - public void Rfc5869ExtractTests(Rfc5869TestCase test) + [MemberData(nameof(GetHkdfTestCases))] + public void ExtractTests(HkdfTestCase test) { byte[] prk = Extract(test.Hash, test.Prk.Length, test.Ikm, test.Salt); Assert.Equal(test.Prk, prk); } [Theory] - [MemberData(nameof(GetRfc5869TestCases))] + [MemberData(nameof(GetHkdfTestCases))] [SkipOnPlatform(TestPlatforms.Browser, "MD5 is not supported on Browser")] - public void Rfc5869ExtractTamperHashTests(Rfc5869TestCase test) + public void ExtractTamperHashTests(HkdfTestCase test) { byte[] prk = Extract(HashAlgorithmName.MD5, 128 / 8, test.Ikm, test.Salt); Assert.NotEqual(test.Prk, prk); } [Theory] - [MemberData(nameof(GetRfc5869TestCases))] - public void Rfc5869ExtractTamperIkmTests(Rfc5869TestCase test) + [MemberData(nameof(GetHkdfTestCases))] + public void ExtractTamperIkmTests(HkdfTestCase test) { byte[] ikm = test.Ikm.ToArray(); ikm[0] ^= 1; @@ -42,8 +42,8 @@ public void Rfc5869ExtractTamperIkmTests(Rfc5869TestCase test) } [Theory] - [MemberData(nameof(GetRfc5869TestCasesWithNonEmptySalt))] - public void Rfc5869ExtractTamperSaltTests(Rfc5869TestCase test) + [MemberData(nameof(GetHkdfTestCasesWithNonEmptySalt))] + public void ExtractTamperSaltTests(HkdfTestCase test) { byte[] salt = test.Salt.ToArray(); salt[0] ^= 1; @@ -52,7 +52,7 @@ public void Rfc5869ExtractTamperSaltTests(Rfc5869TestCase test) } [Fact] - public void Rfc5869ExtractDefaultHash() + public void ExtractDefaultHash() { byte[] ikm = new byte[20]; byte[] salt = new byte[20]; @@ -62,7 +62,7 @@ public void Rfc5869ExtractDefaultHash() } [Fact] - public void Rfc5869ExtractNonsensicalHash() + public void ExtractNonsensicalHash() { byte[] ikm = new byte[20]; byte[] salt = new byte[20]; @@ -72,7 +72,7 @@ public void Rfc5869ExtractNonsensicalHash() } [Fact] - public void Rfc5869ExtractEmptyIkm() + public void ExtractEmptyIkm() { byte[] salt = new byte[20]; byte[] ikm = Array.Empty(); @@ -83,7 +83,7 @@ public void Rfc5869ExtractEmptyIkm() } [Fact] - public void Rfc5869ExtractEmptySalt() + public void ExtractEmptySalt() { byte[] ikm = new byte[20]; byte[] salt = Array.Empty(); @@ -92,15 +92,15 @@ public void Rfc5869ExtractEmptySalt() } [Theory] - [MemberData(nameof(GetRfc5869TestCases))] - public void Rfc5869ExpandTests(Rfc5869TestCase test) + [MemberData(nameof(GetHkdfTestCases))] + public void ExpandTests(HkdfTestCase test) { byte[] okm = Expand(test.Hash, test.Prk, test.Okm.Length, test.Info); Assert.Equal(test.Okm, okm); } [Fact] - public void Rfc5869ExpandDefaultHash() + public void ExpandDefaultHash() { byte[] prk = new byte[20]; AssertExtensions.Throws( @@ -109,7 +109,7 @@ public void Rfc5869ExpandDefaultHash() } [Fact] - public void Rfc5869ExpandNonsensicalHash() + public void ExpandNonsensicalHash() { byte[] prk = new byte[20]; AssertExtensions.Throws( @@ -118,8 +118,8 @@ public void Rfc5869ExpandNonsensicalHash() } [Theory] - [MemberData(nameof(GetRfc5869TestCases))] - public void Rfc5869ExpandTamperPrkTests(Rfc5869TestCase test) + [MemberData(nameof(GetHkdfTestCases))] + public void ExpandTamperPrkTests(HkdfTestCase test) { byte[] prk = test.Prk.ToArray(); prk[0] ^= 1; @@ -129,7 +129,7 @@ public void Rfc5869ExpandTamperPrkTests(Rfc5869TestCase test) [Theory] [MemberData(nameof(GetPrkTooShortTestCases))] - public void Rfc5869ExpandPrkTooShort(HashAlgorithmName hash, int prkSize) + public void ExpandPrkTooShort(HashAlgorithmName hash, int prkSize) { byte[] prk = new byte[prkSize]; AssertExtensions.Throws( @@ -138,7 +138,7 @@ public void Rfc5869ExpandPrkTooShort(HashAlgorithmName hash, int prkSize) } [Fact] - public void Rfc5869ExpandOkmMaxSize() + public void ExpandOkmMaxSize() { byte[] prk = new byte[20]; @@ -148,15 +148,15 @@ public void Rfc5869ExpandOkmMaxSize() } [Theory] - [MemberData(nameof(GetRfc5869TestCases))] - public void Rfc5869DeriveKeyTests(Rfc5869TestCase test) + [MemberData(nameof(GetHkdfTestCases))] + public void DeriveKeyTests(HkdfTestCase test) { byte[] okm = DeriveKey(test.Hash, test.Ikm, test.Okm.Length, test.Salt, test.Info); Assert.Equal(test.Okm, okm); } [Fact] - public void Rfc5869DeriveKeyDefaultHash() + public void DeriveKeyDefaultHash() { byte[] ikm = new byte[20]; AssertExtensions.Throws( @@ -165,7 +165,7 @@ public void Rfc5869DeriveKeyDefaultHash() } [Fact] - public void Rfc5869DeriveKeyNonSensicalHash() + public void DeriveKeyNonSensicalHash() { byte[] ikm = new byte[20]; AssertExtensions.Throws( @@ -174,8 +174,8 @@ public void Rfc5869DeriveKeyNonSensicalHash() } [Theory] - [MemberData(nameof(GetRfc5869TestCases))] - public void Rfc5869DeriveKeyTamperIkmTests(Rfc5869TestCase test) + [MemberData(nameof(GetHkdfTestCases))] + public void DeriveKeyTamperIkmTests(HkdfTestCase test) { byte[] ikm = test.Ikm.ToArray(); ikm[0] ^= 1; @@ -184,8 +184,8 @@ public void Rfc5869DeriveKeyTamperIkmTests(Rfc5869TestCase test) } [Theory] - [MemberData(nameof(GetRfc5869TestCasesWithNonEmptySalt))] - public void Rfc5869DeriveKeyTamperSaltTests(Rfc5869TestCase test) + [MemberData(nameof(GetHkdfTestCasesWithNonEmptySalt))] + public void DeriveKeyTamperSaltTests(HkdfTestCase test) { byte[] salt = test.Salt.ToArray(); salt[0] ^= 1; @@ -194,8 +194,8 @@ public void Rfc5869DeriveKeyTamperSaltTests(Rfc5869TestCase test) } [Theory] - [MemberData(nameof(GetRfc5869TestCasesWithNonEmptyInfo))] - public void Rfc5869DeriveKeyTamperInfoTests(Rfc5869TestCase test) + [MemberData(nameof(GetHkdfTestCasesWithNonEmptyInfo))] + public void DeriveKeyTamperInfoTests(HkdfTestCase test) { byte[] info = test.Info.ToArray(); info[0] ^= 1; @@ -203,17 +203,33 @@ public void Rfc5869DeriveKeyTamperInfoTests(Rfc5869TestCase test) Assert.NotEqual(test.Okm, okm); } - public static IEnumerable GetRfc5869TestCases() + [Theory] + [MemberData(nameof(Sha3TestCases))] + public void Sha3Tests(HkdfTestCase test) + { + if (PlatformDetection.SupportsSha3) + { + byte[] okm = DeriveKey(test.Hash, test.Ikm, test.Okm.Length, test.Salt, test.Info); + Assert.Equal(test.Okm, okm); + } + else + { + Assert.Throws(() => + DeriveKey(test.Hash, test.Ikm, test.Okm.Length, test.Salt, test.Info)); + } + } + + public static IEnumerable GetHkdfTestCases() { - foreach (Rfc5869TestCase test in Rfc5869TestCases) + foreach (HkdfTestCase test in Rfc5869TestCases) { yield return new object[] { test }; } } - public static IEnumerable GetRfc5869TestCasesWithNonEmptySalt() + public static IEnumerable GetHkdfTestCasesWithNonEmptySalt() { - foreach (Rfc5869TestCase test in Rfc5869TestCases) + foreach (HkdfTestCase test in Rfc5869TestCases) { if (test.Salt != null && test.Salt.Length != 0) { @@ -222,9 +238,9 @@ public static IEnumerable GetRfc5869TestCasesWithNonEmptySalt() } } - public static IEnumerable GetRfc5869TestCasesWithNonEmptyInfo() + public static IEnumerable GetHkdfTestCasesWithNonEmptyInfo() { - foreach (Rfc5869TestCase test in Rfc5869TestCases) + foreach (HkdfTestCase test in Rfc5869TestCases) { if (test.Info != null && test.Info.Length != 0) { @@ -245,11 +261,18 @@ public static IEnumerable GetPrkTooShortTestCases() { yield return new object[] { HashAlgorithmName.MD5, 128 / 8 - 1 }; } + + if (PlatformDetection.SupportsSha3) + { + yield return new object[] { HashAlgorithmName.SHA3_256, SHA3_256.HashSizeInBytes - 1 }; + yield return new object[] { HashAlgorithmName.SHA3_384, SHA3_384.HashSizeInBytes - 1 }; + yield return new object[] { HashAlgorithmName.SHA3_512, SHA3_512.HashSizeInBytes - 1 }; + } } - private static Rfc5869TestCase[] Rfc5869TestCases { get; } = new Rfc5869TestCase[7] + private static HkdfTestCase[] Rfc5869TestCases { get; } = new HkdfTestCase[7] { - new Rfc5869TestCase() + new HkdfTestCase() { Name = "Basic test case with SHA-256", Hash = HashAlgorithmName.SHA256, @@ -264,7 +287,7 @@ public static IEnumerable GetPrkTooShortTestCases() "2d2d0a90cf1a5a4c5db02d56ecc4c5bf" + "34007208d5b887185865").HexToByteArray(), }, - new Rfc5869TestCase() + new HkdfTestCase() { Name = "Test with SHA-256 and longer inputs/outputs", Hash = HashAlgorithmName.SHA256, @@ -297,7 +320,7 @@ public static IEnumerable GetPrkTooShortTestCases() "cc30c58179ec3e87c14c01d5c1f3434f" + "1d87").HexToByteArray(), }, - new Rfc5869TestCase() + new HkdfTestCase() { Name = "Test with SHA-256 and zero-length salt/info", Hash = HashAlgorithmName.SHA256, @@ -312,7 +335,7 @@ public static IEnumerable GetPrkTooShortTestCases() "b8a11f5c5ee1879ec3454e5f3c738d2d" + "9d201395faa4b61a96c8").HexToByteArray(), }, - new Rfc5869TestCase() + new HkdfTestCase() { Name = "Basic test case with SHA-1", Hash = HashAlgorithmName.SHA1, @@ -325,7 +348,7 @@ public static IEnumerable GetPrkTooShortTestCases() "a4f14b822f5b091568a9cdd4f155fda2" + "c22e422478d305f3f896").HexToByteArray(), }, - new Rfc5869TestCase() + new HkdfTestCase() { Name = "Test with SHA-1 and longer inputs/outputs", Hash = HashAlgorithmName.SHA1, @@ -356,7 +379,7 @@ public static IEnumerable GetPrkTooShortTestCases() "927336d0441f4c4300e2cff0d0900b52" + "d3b4").HexToByteArray(), }, - new Rfc5869TestCase() + new HkdfTestCase() { Name = "Test with SHA-1 and zero-length salt/info", Hash = HashAlgorithmName.SHA1, @@ -369,7 +392,7 @@ public static IEnumerable GetPrkTooShortTestCases() "b9ae52057220a306e07b6b87e8df21d0" + "ea00033de03984d34918").HexToByteArray(), }, - new Rfc5869TestCase() + new HkdfTestCase() { Name = "Test with SHA-1, salt not provided (defaults to HashLen zero octets), zero-length info", Hash = HashAlgorithmName.SHA1, @@ -384,7 +407,55 @@ public static IEnumerable GetPrkTooShortTestCases() }, }; - public struct Rfc5869TestCase + public static IEnumerable Sha3TestCases + { + // These cases were generated from the openssl kdf command. + // openssl kdf -keylen 8 -kdfopt digest:SHA3-256 -kdfopt hexkey:000102030405060708090A0B0C0D0E0F \ + // -kdfopt salt:mysalt -kdfopt info:myinfo -binary HKDF | xxd -p + get + { + yield return new object[] + { + new HkdfTestCase + { + Name = "SHA3-256 with salt and info", + Hash = HashAlgorithmName.SHA3_256, + Ikm = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F".HexToByteArray(), + Salt = "mysalt"u8.ToArray(), + Info = "myinfo"u8.ToArray(), + Okm = "35bd9d1c75cf7e30".HexToByteArray(), + } + }; + + yield return new object[] + { + new HkdfTestCase + { + Name = "SHA3-384 with salt and info", + Hash = HashAlgorithmName.SHA3_384, + Ikm = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F".HexToByteArray(), + Salt = "mysalt"u8.ToArray(), + Info = "myinfo"u8.ToArray(), + Okm = "323a8ab50c7190c8".HexToByteArray(), + } + }; + + yield return new object[] + { + new HkdfTestCase + { + Name = "SHA3-512 with salt and info", + Hash = HashAlgorithmName.SHA3_512, + Ikm = "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F".HexToByteArray(), + Salt = "mysalt"u8.ToArray(), + Info = "myinfo"u8.ToArray(), + Okm = "27693b36a489e9f1".HexToByteArray(), + } + }; + } + } + + public struct HkdfTestCase { public string Name { get; set; } public HashAlgorithmName Hash { get; set; } @@ -415,7 +486,7 @@ protected override byte[] DeriveKey(HashAlgorithmName hash, byte[] ikm, int outp } [Fact] - public void Rfc5869ExtractNullIkm() + public void ExtractNullIkm() { byte[] salt = new byte[20]; AssertExtensions.Throws( @@ -424,7 +495,7 @@ public void Rfc5869ExtractNullIkm() } [Fact] - public void Rfc5869ExpandOkmMaxSizePlusOne() + public void ExpandOkmMaxSizePlusOne() { byte[] prk = new byte[20]; AssertExtensions.Throws( @@ -433,7 +504,7 @@ public void Rfc5869ExpandOkmMaxSizePlusOne() } [Fact] - public void Rfc5869ExpandOkmPotentiallyOverflowingValue() + public void ExpandOkmPotentiallyOverflowingValue() { byte[] prk = new byte[20]; AssertExtensions.Throws( @@ -442,7 +513,7 @@ public void Rfc5869ExpandOkmPotentiallyOverflowingValue() } [Fact] - public void Rfc5869ExpandOutputLengthZero() + public void ExpandOutputLengthZero() { byte[] prk = new byte[20]; AssertExtensions.Throws( @@ -451,7 +522,7 @@ public void Rfc5869ExpandOutputLengthZero() } [Fact] - public void Rfc5869ExpandOutputLengthLessThanZero() + public void ExpandOutputLengthLessThanZero() { byte[] prk = new byte[20]; AssertExtensions.Throws( @@ -460,7 +531,7 @@ public void Rfc5869ExpandOutputLengthLessThanZero() } [Fact] - public void Rfc5869DeriveKeyNullIkm() + public void DeriveKeyNullIkm() { AssertExtensions.Throws( "ikm", @@ -468,7 +539,7 @@ public void Rfc5869DeriveKeyNullIkm() } [Fact] - public void Rfc5869DeriveKeyOkmMaxSizePlusOne() + public void DeriveKeyOkmMaxSizePlusOne() { byte[] ikm = new byte[20]; AssertExtensions.Throws( @@ -477,7 +548,7 @@ public void Rfc5869DeriveKeyOkmMaxSizePlusOne() } [Fact] - public void Rfc5869DeriveKeyOkmPotentiallyOverflowingValue() + public void DeriveKeyOkmPotentiallyOverflowingValue() { byte[] ikm = new byte[20]; AssertExtensions.Throws( @@ -486,7 +557,7 @@ public void Rfc5869DeriveKeyOkmPotentiallyOverflowingValue() } [Fact] - public void Rfc5869DeriveOutputLengthZero() + public void DeriveOutputLengthZero() { byte[] ikm = new byte[20]; AssertExtensions.Throws( @@ -495,7 +566,7 @@ public void Rfc5869DeriveOutputLengthZero() } [Fact] - public void Rfc5869DeriveOutputLengthLessThanZero() + public void DeriveOutputLengthLessThanZero() { byte[] ikm = new byte[20]; AssertExtensions.Throws( @@ -528,7 +599,7 @@ protected override byte[] DeriveKey(HashAlgorithmName hash, byte[] ikm, int outp } [Fact] - public void Rfc5869ExtractPrkTooLong() + public void ExtractPrkTooLong() { byte[] prk = new byte[24]; @@ -550,7 +621,7 @@ public void Rfc5869ExtractPrkTooLong() } [Fact] - public void Rfc5869OkmMaxSizePlusOne() + public void OkmMaxSizePlusOne() { byte[] prk = new byte[20]; byte[] okm = new byte[20 * 255 + 1]; @@ -560,7 +631,7 @@ public void Rfc5869OkmMaxSizePlusOne() } [Fact] - public void Rfc5869OkmMaxSizePotentiallyOverflowingValue() + public void OkmMaxSizePotentiallyOverflowingValue() { byte[] prk = new byte[20]; byte[] okm = new byte[8421505]; @@ -570,7 +641,7 @@ public void Rfc5869OkmMaxSizePotentiallyOverflowingValue() } [Fact] - public void Rfc5869ExpandOutputLengthZero() + public void ExpandOutputLengthZero() { byte[] prk = new byte[20]; byte[] okm = new byte[0]; @@ -581,7 +652,7 @@ public void Rfc5869ExpandOutputLengthZero() } [Fact] - public void Rfc5869DeriveKeySpanOkmMaxSizePlusOne() + public void DeriveKeySpanOkmMaxSizePlusOne() { byte[] ikm = new byte[20]; byte[] okm = new byte[20 * 255 + 1]; @@ -591,7 +662,7 @@ public void Rfc5869DeriveKeySpanOkmMaxSizePlusOne() } [Fact] - public void Rfc5869DeriveKeySpanOkmPotentiallyOverflowingValue() + public void DeriveKeySpanOkmPotentiallyOverflowingValue() { byte[] ikm = new byte[20]; byte[] okm = new byte[8421505]; @@ -601,7 +672,7 @@ public void Rfc5869DeriveKeySpanOkmPotentiallyOverflowingValue() } [Fact] - public void Rfc5869DeriveKeyOutputLengthZero() + public void DeriveKeyOutputLengthZero() { byte[] ikm = new byte[20]; byte[] okm = new byte[0]; @@ -616,7 +687,7 @@ public void Rfc5869DeriveKeyOutputLengthZero() [InlineData(0, 10)] // Output +10 offset over ikm [InlineData(10, 0)] // ikm +10 offset over output [InlineData(10, 20)] // Both offset, output +10 over ikm - public void Rfc5869ExtractOverlapsPrkOverKeyMaterial(int ikmOffset, int outputOffset) + public void ExtractOverlapsPrkOverKeyMaterial(int ikmOffset, int outputOffset) { ReadOnlySpan ikm = "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b".HexToByteArray(); ReadOnlySpan salt = "000102030405060708090a0b0c".HexToByteArray(); @@ -637,7 +708,7 @@ public void Rfc5869ExtractOverlapsPrkOverKeyMaterial(int ikmOffset, int outputOf [InlineData(0, 10)] // Output +10 offset over salt [InlineData(10, 0)] // salt +10 offset over output [InlineData(10, 20)] // Both offset, output +10 over salt - public void Rfc5869ExtractOverlapsPrkOverSalt(int saltOffset, int outputOffset) + public void ExtractOverlapsPrkOverSalt(int saltOffset, int outputOffset) { ReadOnlySpan ikm = "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b".HexToByteArray(); ReadOnlySpan salt = "000102030405060708090a0b0c".HexToByteArray(); @@ -658,7 +729,7 @@ public void Rfc5869ExtractOverlapsPrkOverSalt(int saltOffset, int outputOffset) [InlineData(0, 10)] // Output +10 offset over info [InlineData(10, 0)] // Info +10 offset over output [InlineData(10, 20)] // Both offset, output +10 over info - public void Rfc5869ExpandOverlapsOutputOverInfo(int infoOffset, int outputOffset) + public void ExpandOverlapsOutputOverInfo(int infoOffset, int outputOffset) { ReadOnlySpan info = ( "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + @@ -686,7 +757,7 @@ public void Rfc5869ExpandOverlapsOutputOverInfo(int infoOffset, int outputOffset [InlineData(0, 10)] // Output +10 offset over info [InlineData(10, 0)] // Info +10 offset over output [InlineData(10, 20)] // Both offset, output +10 over info - public void Rfc5869ExpandOverlapsOutputOverInfoShortOkm(int infoOffset, int outputOffset) + public void ExpandOverlapsOutputOverInfoShortOkm(int infoOffset, int outputOffset) { ReadOnlySpan info = ( "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + @@ -712,7 +783,7 @@ public void Rfc5869ExpandOverlapsOutputOverInfoShortOkm(int infoOffset, int outp [InlineData(0, 10)] // Output +10 offset over prk [InlineData(10, 0)] // Prk +10 offset over output [InlineData(10, 20)] // Both offset, output +10 over prk - public void Rfc5869ExpandOverlapsOutputOverPrk(int prkOffset, int outputOffset) + public void ExpandOverlapsOutputOverPrk(int prkOffset, int outputOffset) { ReadOnlySpan info = ( "b0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecf" + diff --git a/src/libraries/System.Security.Cryptography/tests/HashAlgorithmNameTests.cs b/src/libraries/System.Security.Cryptography/tests/HashAlgorithmNameTests.cs index e4d78699bfdd1c..70d1056a9abf22 100644 --- a/src/libraries/System.Security.Cryptography/tests/HashAlgorithmNameTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/HashAlgorithmNameTests.cs @@ -60,6 +60,9 @@ public static IEnumerable ValidInputs yield return new object[] { "2.16.840.1.101.3.4.2.1", HashAlgorithmName.SHA256 }; yield return new object[] { "2.16.840.1.101.3.4.2.2", HashAlgorithmName.SHA384 }; yield return new object[] { "2.16.840.1.101.3.4.2.3", HashAlgorithmName.SHA512 }; + yield return new object[] { "2.16.840.1.101.3.4.2.8", HashAlgorithmName.SHA3_256 }; + yield return new object[] { "2.16.840.1.101.3.4.2.9", HashAlgorithmName.SHA3_384 }; + yield return new object[] { "2.16.840.1.101.3.4.2.10", HashAlgorithmName.SHA3_512 }; } } } diff --git a/src/libraries/System.Security.Cryptography/tests/HashAlgorithmTestDriver.cs b/src/libraries/System.Security.Cryptography/tests/HashAlgorithmTestDriver.cs index 8890808c6a0cca..8443c222edaa6b 100644 --- a/src/libraries/System.Security.Cryptography/tests/HashAlgorithmTestDriver.cs +++ b/src/libraries/System.Security.Cryptography/tests/HashAlgorithmTestDriver.cs @@ -10,8 +10,10 @@ namespace System.Security.Cryptography.Tests { - public abstract class HashAlgorithmTestDriver + public abstract class HashAlgorithmTestDriver where THashTrait : IHashTrait { + public static bool IsSupported => THashTrait.IsSupported; + public static bool IsNotSupported => !IsSupported; protected abstract HashAlgorithm Create(); protected abstract bool TryHashData(ReadOnlySpan source, Span destination, out int bytesWritten); protected abstract byte[] HashData(byte[] source); @@ -191,19 +193,19 @@ private void VerifyTransformBlockComputeHashInteraction(byte[] block1, byte[] bl } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void HashData_ByteArray_Null() { AssertExtensions.Throws("source", () => HashData((byte[])null)); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void HashData_BufferTooSmall() { AssertExtensions.Throws("destination", () => HashData(Span.Empty, default)); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void VerifyObjectDisposedException() { HashAlgorithm hash = Create(); @@ -216,7 +218,7 @@ public void VerifyObjectDisposedException() Assert.Throws(() => hash.TransformFinalBlock(Array.Empty(), 0, 0)); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void VerifyHashNotYetFinalized() { using (HashAlgorithm hash = Create()) @@ -226,7 +228,7 @@ public void VerifyHashNotYetFinalized() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void InvalidInput_ComputeHash() { using (HashAlgorithm hash = Create()) @@ -236,7 +238,7 @@ public void InvalidInput_ComputeHash() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void InvalidInput_TransformBlock() { using (HashAlgorithm hash = Create()) @@ -248,7 +250,7 @@ public void InvalidInput_TransformBlock() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void InvalidInput_TransformFinalBlock() { using (HashAlgorithm hash = Create()) @@ -404,20 +406,43 @@ protected async Task VerifyRepeatingAsync(string input, int repeatCount, string } } - [Fact] + [ConditionalFact(nameof(IsNotSupported))] + public async Task HashData_NotSupported() + { + byte[] buffer = new byte[THashTrait.HashSizeInBytes]; + Assert.Throws(() => HashData(Array.Empty())); + Assert.Throws(() => HashData(ReadOnlySpan.Empty)); + Assert.Throws(() => HashData(ReadOnlySpan.Empty, buffer)); + Assert.Throws(() => TryHashData(ReadOnlySpan.Empty, buffer, out _)); + + Assert.Throws(() => HashData(Stream.Null)); + Assert.Throws(() => HashData(Stream.Null, buffer)); + await Assert.ThrowsAsync(async () => + await HashDataAsync(Stream.Null, default(CancellationToken))); + await Assert.ThrowsAsync(async () => + await HashDataAsync(Stream.Null, buffer, default(CancellationToken))); + } + + [ConditionalFact(nameof(IsNotSupported))] + public void Create_NotSupported() + { + Assert.Throws(() => Create()); + } + + [ConditionalFact(nameof(IsSupported))] public void HashData_Null_Stream_Throws() { AssertExtensions.Throws("source", () => HashData((Stream)null)); AssertExtensions.Throws("source", () => HashData((Stream)null, Span.Empty)); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void HashData_ShortDestination_Throws() { AssertExtensions.Throws("destination", () => HashData(Stream.Null, Span.Empty)); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void HashDataAsync_Null_Stream_Throws() { AssertExtensions.Throws( @@ -429,7 +454,7 @@ public void HashDataAsync_Null_Stream_Throws() () => HashDataAsync((Stream)null, Memory.Empty, cancellationToken: default)); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void HashDataAsync_ShortDestination_Throws() { AssertExtensions.Throws( @@ -437,7 +462,7 @@ public void HashDataAsync_ShortDestination_Throws() () => HashDataAsync(Stream.Null, Memory.Empty, cancellationToken: default)); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void HashDataAsync_Buffer_CancelledToken() { Memory buffer = new byte[512 / 8]; @@ -447,7 +472,7 @@ public void HashDataAsync_Buffer_CancelledToken() AssertExtensions.FilledWith(0, buffer.Span); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void HashDataAsync_Allocating_CancelledToken() { CancellationToken cancelledToken = new CancellationToken(canceled: true); @@ -455,7 +480,7 @@ public void HashDataAsync_Allocating_CancelledToken() Assert.True(waitable.IsCanceled, nameof(waitable.IsCanceled)); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void InvalidInput_Null() { using (HashAlgorithm hash = Create()) @@ -466,7 +491,7 @@ public void InvalidInput_Null() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void InvalidInput_NegativeOffset() { using (HashAlgorithm hash = Create()) @@ -475,7 +500,7 @@ public void InvalidInput_NegativeOffset() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void InvalidInput_NegativeCount() { using (HashAlgorithm hash = Create()) @@ -484,7 +509,7 @@ public void InvalidInput_NegativeCount() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void InvalidInput_TooBigOffset() { using (HashAlgorithm hash = Create()) @@ -493,7 +518,7 @@ public void InvalidInput_TooBigOffset() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void InvalidInput_TooBigCount() { byte[] nonEmpty = new byte[53]; @@ -507,7 +532,7 @@ public void InvalidInput_TooBigCount() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void BoundaryCondition_Count0() { byte[] nonEmpty = new byte[53]; @@ -533,7 +558,7 @@ public void BoundaryCondition_Count0() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void OffsetAndCountRespected() { byte[] dataA = { 1, 1, 2, 3, 5, 8 }; @@ -550,7 +575,7 @@ public void OffsetAndCountRespected() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void ComputeHash_TryComputeHash_HashSetExplicitlyByBoth() { using (HashAlgorithm hash = Create()) @@ -569,7 +594,7 @@ public void ComputeHash_TryComputeHash_HashSetExplicitlyByBoth() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void Dispose_TryComputeHash_ThrowsException() { HashAlgorithm hash = Create(); @@ -578,7 +603,7 @@ public void Dispose_TryComputeHash_ThrowsException() Assert.Throws(() => hash.TryComputeHash(new byte[1], new byte[1], out int bytesWritten)); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void Initialize_TransformBlock() { byte[] hashInput = new byte[] { 1, 2, 3, 4, 5 }; @@ -600,7 +625,7 @@ public void Initialize_TransformBlock() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void Initialize_TransformBlock_Unused() { byte[] hashInput = new byte[] { 1, 2, 3, 4, 5 }; @@ -621,7 +646,7 @@ public void Initialize_TransformBlock_Unused() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void Initialize_DoubleInitialize_Works() { byte[] hashInput = new byte[] { 1, 2, 3, 4, 5 }; @@ -645,4 +670,10 @@ public void Initialize_DoubleInitialize_Works() } } } + + public interface IHashTrait + { + static abstract bool IsSupported { get; } + static abstract int HashSizeInBytes { get; } + } } diff --git a/src/libraries/System.Security.Cryptography/tests/HashDerivedTests.cs b/src/libraries/System.Security.Cryptography/tests/HashDerivedTests.cs index 6734bca6bb5a53..1c58b8758eef7f 100644 --- a/src/libraries/System.Security.Cryptography/tests/HashDerivedTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/HashDerivedTests.cs @@ -11,28 +11,28 @@ public static class HashDerivedTests public static void HashSize_SetForDerived_SHA1() { using DerivedSHA1 sha = new DerivedSHA1(); - Assert.Equal(160, sha.HashSize); + Assert.Equal(SHA1.HashSizeInBits, sha.HashSize); } [Fact] public static void HashSize_SetForDerived_SHA256() { using DerivedSHA256 sha = new DerivedSHA256(); - Assert.Equal(256, sha.HashSize); + Assert.Equal(SHA256.HashSizeInBits, sha.HashSize); } [Fact] public static void HashSize_SetForDerived_SHA384() { using DerivedSHA384 sha = new DerivedSHA384(); - Assert.Equal(384, sha.HashSize); + Assert.Equal(SHA384.HashSizeInBits, sha.HashSize); } [Fact] public static void HashSize_SetForDerived_SHA512() { using DerivedSHA512 sha = new DerivedSHA512(); - Assert.Equal(512, sha.HashSize); + Assert.Equal(SHA512.HashSizeInBits, sha.HashSize); } [Fact] @@ -40,7 +40,28 @@ public static void HashSize_SetForDerived_SHA512() public static void HashSize_SetForDerived_MD5() { using DerivedMD5 sha = new DerivedMD5(); - Assert.Equal(128, sha.HashSize); + Assert.Equal(MD5.HashSizeInBits, sha.HashSize); + } + + [Fact] + public static void HashSize_SetForDerived_SHA3_256() + { + using DerivedSHA3_256 sha = new DerivedSHA3_256(); + Assert.Equal(SHA3_256.HashSizeInBits, sha.HashSize); + } + + [Fact] + public static void HashSize_SetForDerived_SHA3_384() + { + using DerivedSHA3_384 sha = new DerivedSHA3_384(); + Assert.Equal(SHA3_384.HashSizeInBits, sha.HashSize); + } + + [Fact] + public static void HashSize_SetForDerived_SHA3_512() + { + using DerivedSHA3_512 sha = new DerivedSHA3_512(); + Assert.Equal(SHA3_512.HashSizeInBits, sha.HashSize); } private class DerivedSHA1 : SHA1 @@ -71,14 +92,28 @@ private class DerivedSHA512 : SHA512 protected override void HashCore(byte[] array, int ibStart, int cbSize) => throw null; } - private class DerivedMD5 : MD5 + private class DerivedSHA3_256 : SHA3_256 { public override void Initialize() => throw null; protected override byte[] HashFinal() => throw null; protected override void HashCore(byte[] array, int ibStart, int cbSize) => throw null; } - private class DerivedHMACMD5 : HMACMD5 + private class DerivedSHA3_384 : SHA3_384 + { + public override void Initialize() => throw null; + protected override byte[] HashFinal() => throw null; + protected override void HashCore(byte[] array, int ibStart, int cbSize) => throw null; + } + + private class DerivedSHA3_512 : SHA3_512 + { + public override void Initialize() => throw null; + protected override byte[] HashFinal() => throw null; + protected override void HashCore(byte[] array, int ibStart, int cbSize) => throw null; + } + + private class DerivedMD5 : MD5 { public override void Initialize() => throw null; protected override byte[] HashFinal() => throw null; diff --git a/src/libraries/System.Security.Cryptography/tests/HmacMD5Tests.cs b/src/libraries/System.Security.Cryptography/tests/HmacMD5Tests.cs index d657f9627b2942..2adf417aec8458 100644 --- a/src/libraries/System.Security.Cryptography/tests/HmacMD5Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/HmacMD5Tests.cs @@ -10,8 +10,14 @@ namespace System.Security.Cryptography.Tests { [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] - public class HmacMD5Tests : Rfc2202HmacTests + public class HmacMD5Tests : Rfc2202HmacTests { + public sealed class Traits : IHmacTrait + { + public static bool IsSupported => true; + public static int HashSizeInBytes => HMACSHA1.HashSizeInBytes; + } + private static readonly byte[][] s_testKeys2202 = { null, @@ -45,6 +51,7 @@ public HmacMD5Tests() protected override int MacSize => HMACMD5.HashSizeInBytes; protected override HMAC Create() => new HMACMD5(); + protected override HMAC Create(byte[] key) => new HMACMD5(key); protected override HashAlgorithm CreateHashAlgorithm() => MD5.Create(); protected override byte[] HashDataOneShot(byte[] key, byte[] source) => HMACMD5.HashData(key, source); @@ -218,5 +225,12 @@ await VerifyRepeatingAsync( hexKey: "000102030405060708090A0B0C0D0E0F", output: "C91E40247251F39BDFE6A7B72A5857F9"); } + + [Fact] + public void HmacMD5_HashSizes() + { + Assert.Equal(128, HMACMD5.HashSizeInBits); + Assert.Equal(16, HMACMD5.HashSizeInBytes); + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/HmacSha1Tests.cs b/src/libraries/System.Security.Cryptography/tests/HmacSha1Tests.cs index 9b5aa3effca47b..6b3b1eed43d8cf 100644 --- a/src/libraries/System.Security.Cryptography/tests/HmacSha1Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/HmacSha1Tests.cs @@ -9,8 +9,14 @@ namespace System.Security.Cryptography.Tests { - public class HmacSha1Tests : Rfc2202HmacTests + public class HmacSha1Tests : Rfc2202HmacTests { + public sealed class Traits : IHmacTrait + { + public static bool IsSupported => true; + public static int HashSizeInBytes => HMACSHA1.HashSizeInBytes; + } + private static readonly byte[][] s_testKeys2202 = { null, @@ -44,6 +50,7 @@ public HmacSha1Tests() protected override int MacSize => HMACSHA1.HashSizeInBytes; protected override HMAC Create() => new HMACSHA1(); + protected override HMAC Create(byte[] key) => new HMACSHA1(key); protected override HashAlgorithm CreateHashAlgorithm() => SHA1.Create(); protected override byte[] HashDataOneShot(byte[] key, byte[] source) => HMACSHA1.HashData(key, source); @@ -241,5 +248,12 @@ await VerifyRepeatingAsync( hexKey: "000102030405060708090A0B0C0D0E0F", output: "5433122F77BCF8A4D9B874B4149823EF5B7C207E"); } + + [Fact] + public void HmacSha1_HashSizes() + { + Assert.Equal(160, HMACSHA1.HashSizeInBits); + Assert.Equal(20, HMACSHA1.HashSizeInBytes); + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/HmacSha256Tests.cs b/src/libraries/System.Security.Cryptography/tests/HmacSha256Tests.cs index dea079824ff1fc..6abef3de5a2a2f 100644 --- a/src/libraries/System.Security.Cryptography/tests/HmacSha256Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/HmacSha256Tests.cs @@ -9,12 +9,19 @@ namespace System.Security.Cryptography.Tests { - public class HmacSha256Tests : Rfc4231HmacTests + public class HmacSha256Tests : Rfc4231HmacTests { + public sealed class Traits : IHmacTrait + { + public static bool IsSupported => true; + public static int HashSizeInBytes => HMACSHA256.HashSizeInBytes; + } + protected override int BlockSize => 64; protected override int MacSize => HMACSHA256.HashSizeInBytes; protected override HMAC Create() => new HMACSHA256(); + protected override HMAC Create(byte[] key) => new HMACSHA256(key); protected override HashAlgorithm CreateHashAlgorithm() => SHA256.Create(); protected override byte[] HashDataOneShot(byte[] key, byte[] source) => HMACSHA256.HashData(key, source); @@ -205,5 +212,12 @@ await VerifyRepeatingAsync( hexKey: "000102030405060708090A0B0C0D0E0F", output: "07EFF8B326B7798C9CCFCBDBE579489AC785A7995A04618B1A2813C26744777D"); } + + [Fact] + public void HmacSha256_HashSizes() + { + Assert.Equal(256, HMACSHA256.HashSizeInBits); + Assert.Equal(32, HMACSHA256.HashSizeInBytes); + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/HmacSha384Tests.cs b/src/libraries/System.Security.Cryptography/tests/HmacSha384Tests.cs index d026442de4bb4a..d17b08a69925ee 100644 --- a/src/libraries/System.Security.Cryptography/tests/HmacSha384Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/HmacSha384Tests.cs @@ -9,12 +9,19 @@ namespace System.Security.Cryptography.Tests { - public class HmacSha384Tests : Rfc4231HmacTests + public class HmacSha384Tests : Rfc4231HmacTests { + public sealed class Traits : IHmacTrait + { + public static bool IsSupported => true; + public static int HashSizeInBytes => HMACSHA384.HashSizeInBytes; + } + protected override int BlockSize => 128; protected override int MacSize => HMACSHA384.HashSizeInBytes; protected override HMAC Create() => new HMACSHA384(); + protected override HMAC Create(byte[] key) => new HMACSHA384(key); protected override HashAlgorithm CreateHashAlgorithm() => SHA384.Create(); protected override byte[] HashDataOneShot(byte[] key, byte[] source) => HMACSHA384.HashData(key, source); @@ -218,5 +225,12 @@ await VerifyRepeatingAsync( hexKey: "000102030405060708090A0B0C0D0E0F", output: "6A0FDC1C54C664AD91C7C157D2670C5D44E4D44EBAD2359A0206974C7088B1A867F76971E6C240C33B33A66BA295BB56"); } + + [Fact] + public void HmacSha384_HashSizes() + { + Assert.Equal(384, HMACSHA384.HashSizeInBits); + Assert.Equal(48, HMACSHA384.HashSizeInBytes); + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/HmacSha3_256Tests.cs b/src/libraries/System.Security.Cryptography/tests/HmacSha3_256Tests.cs new file mode 100644 index 00000000000000..fb5b540ac506d0 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/tests/HmacSha3_256Tests.cs @@ -0,0 +1,233 @@ +// 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.IO; +using System.Threading; +using System.Threading.Tasks; +using Test.Cryptography; +using Xunit; + +namespace System.Security.Cryptography.Tests +{ + public class HmacSha3_256Tests : HmacTests + { + public sealed class Traits : IHmacTrait + { + public static bool IsSupported => HMACSHA3_256.IsSupported; + public static int HashSizeInBytes => HMACSHA3_256.HashSizeInBytes; + } + + protected override int BlockSize => 136; + protected override int MacSize => HMACSHA3_256.HashSizeInBytes; + + protected override HMAC Create() => new HMACSHA3_256(); + protected override HMAC Create(byte[] key) => new HMACSHA3_256(key); + protected override HashAlgorithm CreateHashAlgorithm() => SHA3_256.Create(); + protected override byte[] HashDataOneShot(byte[] key, byte[] source) => + HMACSHA3_256.HashData(key, source); + + protected override byte[] HashDataOneShot(ReadOnlySpan key, ReadOnlySpan source) => + HMACSHA3_256.HashData(key, source); + + protected override int HashDataOneShot(ReadOnlySpan key, ReadOnlySpan source, Span destination) => + HMACSHA3_256.HashData(key, source, destination); + + protected override bool TryHashDataOneShot(ReadOnlySpan key, ReadOnlySpan source, Span destination, out int written) => + HMACSHA3_256.TryHashData(key, source, destination, out written); + + protected override byte[] HashDataOneShot(ReadOnlySpan key, Stream source) => + HMACSHA3_256.HashData(key, source); + + protected override byte[] HashDataOneShot(byte[] key, Stream source) => + HMACSHA3_256.HashData(key, source); + + protected override int HashDataOneShot(ReadOnlySpan key, Stream source, Span destination) => + HMACSHA3_256.HashData(key, source, destination); + + protected override ValueTask HashDataOneShotAsync( + ReadOnlyMemory key, + Stream source, + Memory destination, + CancellationToken cancellationToken) => HMACSHA3_256.HashDataAsync(key, source, destination, cancellationToken); + + protected override ValueTask HashDataOneShotAsync( + ReadOnlyMemory key, + Stream source, + CancellationToken cancellationToken) => HMACSHA3_256.HashDataAsync(key, source, cancellationToken); + + protected override ValueTask HashDataOneShotAsync( + byte[] key, + Stream source, + CancellationToken cancellationToken) => HMACSHA3_256.HashDataAsync(key, source, cancellationToken); + + private static readonly byte[][] s_testKeys = new byte[][] + { + // From: https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-256.pdf + null, + ByteUtils.HexToByteArray("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + ByteUtils.HexToByteArray( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + + "8081828384858687"), + ByteUtils.HexToByteArray( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + + "808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f" + + "a0a1a2a3a4a5a6a7"), + ByteUtils.HexToByteArray("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"), + }; + + private static readonly byte[][] s_testData = new byte[][] + { + null, + ByteUtils.HexToByteArray("53616d706c65206d65737361676520666f72206b65796c656e3c626c6f636b6c656e"), + ByteUtils.HexToByteArray("53616d706c65206d65737361676520666f72206b65796c656e3d626c6f636b6c656e"), + ByteUtils.HexToByteArray("53616d706c65206d65737361676520666f72206b65796c656e3e626c6f636b6c656e"), + ByteUtils.HexToByteArray("53616d706c65206d65737361676520666f72206b65796c656e3c626c6f636b6c656e2c2077697468207472756e636174656420746167"), + }; + + private static readonly byte[][] s_testMacs = new byte[][] + { + null, + ByteUtils.HexToByteArray("4fe8e202c4f058e8dddc23d8c34e467343e23555e24fc2f025d598f558f67205"), + ByteUtils.HexToByteArray("68b94e2e538a9be4103bebb5aa016d47961d4d1aa906061313b557f8af2c3faa"), + ByteUtils.HexToByteArray("9bcf2c238e235c3ce88404e813bd2f3a97185ac6f238c63d6229a00b07974258"), + ByteUtils.HexToByteArray("c8dc7148d8c1423aa549105dafdf9cad"), // Truncated test case. + }; + + + public HmacSha3_256Tests() : base(s_testKeys, s_testData, s_testMacs) + { + } + + [ConditionalTheory(nameof(IsSupported))] + [MemberData(nameof(TestCaseIds))] + public void HmacSha3_256_VerifyTestCases(int caseId) + { + VerifyHmac(caseId, s_testMacs[caseId]); + } + + public static IEnumerable TestCaseIds + { + get + { + for (int i = 1; i < s_testKeys.Length; i++) + { + yield return new object[] { i }; + } + } + } + + [ConditionalFact(nameof(IsSupported))] + public void HmacSha3_256_Rfc2104_2() + { + VerifyHmacRfc2104_2(); + } + + [ConditionalFact(nameof(IsSupported))] + public void HmacSha3_256_ThrowsArgumentNullForNullConstructorKey() + { + AssertExtensions.Throws("key", () => new HMACSHA3_256(null)); + } + + [ConditionalFact(nameof(IsSupported))] + public void HmacSha3_256_EmptyKey() + { + VerifyRepeating( + input: "Crypto is fun!", + 1, + hexKey: "", + output: "c49c24ae6dce7e90d5e2853ad9e647d89ac3dd04eb71aa0912ab4b4b1068ba6a"); + } + + [ConditionalFact(nameof(IsSupported))] + public void HmacSha3_256_Stream_MultipleOf4096() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl sha3-256 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "0102030405060708", + 1024, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "F09DD1B814BF4A576FF8AEAFF69509E3093895426F441A428953221F3CB9E421"); + } + + [ConditionalFact(nameof(IsSupported))] + public void HmacSha3_256_Stream_NotMultipleOf4096() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl sha3-256 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "0102030405060708", + 1025, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "F1DB96FF2B53CBA0338FF519BFA10153731DB48A63C26EB66294895B220F72B5"); + } + + [ConditionalFact(nameof(IsSupported))] + public void HmacSha3_256_Stream_Empty() + { + // Verfied with: + // echo -n "" | openssl sha3-256 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "", + 0, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "72756291FF30F3E916BEF99EC9CF5938B25D90BBCAC1BDB1E1E6564E8EC6FDA5"); + } + + [ConditionalFact(nameof(IsSupported))] + public async Task HmacSha3_256_Stream_MultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl sha3-256 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "0102030405060708", + 1024, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "F09DD1B814BF4A576FF8AEAFF69509E3093895426F441A428953221F3CB9E421"); + } + + [ConditionalFact(nameof(IsSupported))] + public async Task HmacSha3_256_Stream_NotMultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl sha3-256 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "0102030405060708", + 1025, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "F1DB96FF2B53CBA0338FF519BFA10153731DB48A63C26EB66294895B220F72B5"); + } + + [ConditionalFact(nameof(IsSupported))] + public async Task HmacSha3_256_Stream_Empty_Async() + { + // Verfied with: + // echo -n "" | openssl sha3-256 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "", + 0, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "72756291FF30F3E916BEF99EC9CF5938B25D90BBCAC1BDB1E1E6564E8EC6FDA5"); + } + + [Fact] + public void HmacSha3_256_HashSizes() + { + Assert.Equal(256, HMACSHA3_256.HashSizeInBits); + Assert.Equal(32, HMACSHA3_256.HashSizeInBytes); + } + + [Fact] + public void HmacSha3_256_IsSupported_AgreesWithPlatformVersion() + { + Assert.Equal(PlatformDetection.SupportsSha3, HMACSHA3_256.IsSupported); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/tests/HmacSha3_384Tests.cs b/src/libraries/System.Security.Cryptography/tests/HmacSha3_384Tests.cs new file mode 100644 index 00000000000000..7dab4a444f5adb --- /dev/null +++ b/src/libraries/System.Security.Cryptography/tests/HmacSha3_384Tests.cs @@ -0,0 +1,241 @@ +// 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.IO; +using System.Threading; +using System.Threading.Tasks; +using Test.Cryptography; +using Xunit; + +namespace System.Security.Cryptography.Tests +{ + public class HmacSha3_384Tests : HmacTests + { + public sealed class Traits : IHmacTrait + { + public static bool IsSupported => HMACSHA3_384.IsSupported; + public static int HashSizeInBytes => HMACSHA3_384.HashSizeInBytes; + } + + protected override int BlockSize => 104; + protected override int MacSize => HMACSHA3_384.HashSizeInBytes; + + protected override HMAC Create() => new HMACSHA3_384(); + protected override HMAC Create(byte[] key) => new HMACSHA3_384(key); + protected override HashAlgorithm CreateHashAlgorithm() => SHA3_384.Create(); + protected override byte[] HashDataOneShot(byte[] key, byte[] source) => + HMACSHA3_384.HashData(key, source); + + protected override byte[] HashDataOneShot(ReadOnlySpan key, ReadOnlySpan source) => + HMACSHA3_384.HashData(key, source); + + protected override int HashDataOneShot(ReadOnlySpan key, ReadOnlySpan source, Span destination) => + HMACSHA3_384.HashData(key, source, destination); + + protected override bool TryHashDataOneShot(ReadOnlySpan key, ReadOnlySpan source, Span destination, out int written) => + HMACSHA3_384.TryHashData(key, source, destination, out written); + + protected override byte[] HashDataOneShot(ReadOnlySpan key, Stream source) => + HMACSHA3_384.HashData(key, source); + + protected override byte[] HashDataOneShot(byte[] key, Stream source) => + HMACSHA3_384.HashData(key, source); + + protected override int HashDataOneShot(ReadOnlySpan key, Stream source, Span destination) => + HMACSHA3_384.HashData(key, source, destination); + + protected override ValueTask HashDataOneShotAsync( + ReadOnlyMemory key, + Stream source, + Memory destination, + CancellationToken cancellationToken) => HMACSHA3_384.HashDataAsync(key, source, destination, cancellationToken); + + protected override ValueTask HashDataOneShotAsync( + ReadOnlyMemory key, + Stream source, + CancellationToken cancellationToken) => HMACSHA3_384.HashDataAsync(key, source, cancellationToken); + + protected override ValueTask HashDataOneShotAsync( + byte[] key, + Stream source, + CancellationToken cancellationToken) => HMACSHA3_384.HashDataAsync(key, source, cancellationToken); + + private static readonly byte[][] s_testKeys = new byte[][] + { + // From: https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-384.pdf + null, + ByteUtils.HexToByteArray( + "000102030405060708090a0b0c0d0e0f1011121314151617" + + "18191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f"), + ByteUtils.HexToByteArray( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + + "6061626364656667"), + ByteUtils.HexToByteArray( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + + "808182838485868788898a8b8c8d8e8f9091929394959697"), + ByteUtils.HexToByteArray( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f"), + }; + + private static readonly byte[][] s_testData = new byte[][] + { + null, + ByteUtils.HexToByteArray("53616d706c65206d65737361676520666f72206b65796c656e3c626c6f636b6c656e"), + ByteUtils.HexToByteArray("53616d706c65206d65737361676520666f72206b65796c656e3d626c6f636b6c656e"), + ByteUtils.HexToByteArray("53616d706c65206d65737361676520666f72206b65796c656e3e626c6f636b6c656e"), + ByteUtils.HexToByteArray("53616d706c65206d65737361676520666f72206b65796c656e3c626c6f636b6c656e2c2077697468207472756e636174656420746167"), + }; + + private static readonly byte[][] s_testMacs = new byte[][] + { + null, + ByteUtils.HexToByteArray( + "d588a3c51f3f2d906e8298c1199aa8ff6296218127f6b38a" + + "90b6afe2c5617725bc99987f79b22a557b6520db710b7f42"), + ByteUtils.HexToByteArray( + "a27d24b592e8c8cbf6d4ce6fc5bf62d8fc98bf2d486640d9" + + "eb8099e24047837f5f3bffbe92dcce90b4ed5b1e7e44fa90"), + ByteUtils.HexToByteArray( + "e5ae4c739f455279368ebf36d4f5354c95aa184c899d3870" + + "e460ebc288ef1f9470053f73f7c6da2a71bcaec38ce7d6ac"), + ByteUtils.HexToByteArray("25f4bf53606e91af79d24a4bb1fd6aecd44414a30c8ebb0a"), // Truncated + }; + + + public HmacSha3_384Tests() : base(s_testKeys, s_testData, s_testMacs) + { + } + + [ConditionalTheory(nameof(IsSupported))] + [MemberData(nameof(TestCaseIds))] + public void HmacSha3_384_VerifyTestCases(int caseId) + { + VerifyHmac(caseId, s_testMacs[caseId]); + } + + public static IEnumerable TestCaseIds + { + get + { + for (int i = 1; i < s_testKeys.Length; i++) + { + yield return new object[] { i }; + } + } + } + + [ConditionalFact(nameof(IsSupported))] + public void HmacSha3_384_Rfc2104_2() + { + VerifyHmacRfc2104_2(); + } + + [ConditionalFact(nameof(IsSupported))] + public void HmacSha3_384_ThrowsArgumentNullForNullConstructorKey() + { + AssertExtensions.Throws("key", () => new HMACSHA3_384(null)); + } + + [ConditionalFact(nameof(IsSupported))] + public void HmacSha3_384_EmptyKey() + { + VerifyRepeating( + input: "Crypto is fun!", + 1, + hexKey: "", + output: "16C079F7D15505E9E541421E63C432A063F39C1E3E953E6DC7B8A81FE5620AFFA430C3E6BE6A0F605755C7C5EE4E347E"); + } + + [ConditionalFact(nameof(IsSupported))] + public void HmacSha3_384_Stream_MultipleOf4096() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl sha3-384 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "0102030405060708", + 1024, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "17D03C8153AF1719F5829C8CBF328D4200900ED1AB038A399B4F256A490BD4D2AB311C71D2ED0C20ABA96E57768CCA6E"); + } + + [ConditionalFact(nameof(IsSupported))] + public void HmacSha3_384_Stream_NotMultipleOf4096() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl sha3-384 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "0102030405060708", + 1025, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "5360719A6A9DFEB1143C2866A7F72EA29404C3DBF37F244A0497F400DA126B2728118863454288F26E3796BE72238958"); + } + + [ConditionalFact(nameof(IsSupported))] + public void HmacSha3_384_Stream_Empty() + { + // Verfied with: + // echo -n "" | openssl sha3-384 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "", + 0, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "5B0196779BDAF859E99869A63C9FDF3821E9100A370B5E9B88F76B9DA87410F99846E7DBB4F8A69368C5C5A834B3128D"); + } + + [ConditionalFact(nameof(IsSupported))] + public async Task HmacSha3_384_Stream_MultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl sha3-384 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "0102030405060708", + 1024, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "17D03C8153AF1719F5829C8CBF328D4200900ED1AB038A399B4F256A490BD4D2AB311C71D2ED0C20ABA96E57768CCA6E"); + } + + [ConditionalFact(nameof(IsSupported))] + public async Task HmacSha3_384_Stream_NotMultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl sha3-384 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "0102030405060708", + 1025, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "5360719A6A9DFEB1143C2866A7F72EA29404C3DBF37F244A0497F400DA126B2728118863454288F26E3796BE72238958"); + } + + [ConditionalFact(nameof(IsSupported))] + public async Task HmacSha3_384_Stream_Empty_Async() + { + // Verfied with: + // echo -n "" | openssl sha3-384 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "", + 0, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "5B0196779BDAF859E99869A63C9FDF3821E9100A370B5E9B88F76B9DA87410F99846E7DBB4F8A69368C5C5A834B3128D"); + } + + [Fact] + public void HmacSha3_384_HashSizes() + { + Assert.Equal(384, HMACSHA3_384.HashSizeInBits); + Assert.Equal(48, HMACSHA3_384.HashSizeInBytes); + } + + [Fact] + public void HmacSha3_384_IsSupported_AgreesWithPlatformVersion() + { + Assert.Equal(PlatformDetection.SupportsSha3, HMACSHA3_384.IsSupported); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/tests/HmacSha3_512Tests.cs b/src/libraries/System.Security.Cryptography/tests/HmacSha3_512Tests.cs new file mode 100644 index 00000000000000..3359ba4e335680 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/tests/HmacSha3_512Tests.cs @@ -0,0 +1,247 @@ +// 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.IO; +using System.Threading; +using System.Threading.Tasks; +using Test.Cryptography; +using Xunit; + +namespace System.Security.Cryptography.Tests +{ + public class HmacSha3_512Tests : HmacTests + { + public sealed class Traits : IHmacTrait + { + public static bool IsSupported => HMACSHA3_512.IsSupported; + public static int HashSizeInBytes => HMACSHA3_512.HashSizeInBytes; + } + + protected override int BlockSize => 72; + protected override int MacSize => HMACSHA3_512.HashSizeInBytes; + + protected override HMAC Create() => new HMACSHA3_512(); + protected override HMAC Create(byte[] key) => new HMACSHA3_512(key); + protected override HashAlgorithm CreateHashAlgorithm() => SHA3_512.Create(); + protected override byte[] HashDataOneShot(byte[] key, byte[] source) => + HMACSHA3_512.HashData(key, source); + + protected override byte[] HashDataOneShot(ReadOnlySpan key, ReadOnlySpan source) => + HMACSHA3_512.HashData(key, source); + + protected override int HashDataOneShot(ReadOnlySpan key, ReadOnlySpan source, Span destination) => + HMACSHA3_512.HashData(key, source, destination); + + protected override bool TryHashDataOneShot(ReadOnlySpan key, ReadOnlySpan source, Span destination, out int written) => + HMACSHA3_512.TryHashData(key, source, destination, out written); + + protected override byte[] HashDataOneShot(ReadOnlySpan key, Stream source) => + HMACSHA3_512.HashData(key, source); + + protected override byte[] HashDataOneShot(byte[] key, Stream source) => + HMACSHA3_512.HashData(key, source); + + protected override int HashDataOneShot(ReadOnlySpan key, Stream source, Span destination) => + HMACSHA3_512.HashData(key, source, destination); + + protected override ValueTask HashDataOneShotAsync( + ReadOnlyMemory key, + Stream source, + Memory destination, + CancellationToken cancellationToken) => HMACSHA3_512.HashDataAsync(key, source, destination, cancellationToken); + + protected override ValueTask HashDataOneShotAsync( + ReadOnlyMemory key, + Stream source, + CancellationToken cancellationToken) => HMACSHA3_512.HashDataAsync(key, source, cancellationToken); + + protected override ValueTask HashDataOneShotAsync( + byte[] key, + Stream source, + CancellationToken cancellationToken) => HMACSHA3_512.HashDataAsync(key, source, cancellationToken); + + private static readonly byte[][] s_testKeys = new byte[][] + { + // From: https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/HMAC_SHA3-512.pdf + null, + ByteUtils.HexToByteArray( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"), + ByteUtils.HexToByteArray( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + + "4041424344454647"), + ByteUtils.HexToByteArray( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f" + + "404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f" + + "606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f" + + "8081828384858687"), + ByteUtils.HexToByteArray( + "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f" + + "202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"), + }; + + private static readonly byte[][] s_testData = new byte[][] + { + null, + ByteUtils.HexToByteArray("53616d706c65206d65737361676520666f72206b65796c656e3c626c6f636b6c656e"), + ByteUtils.HexToByteArray("53616d706c65206d65737361676520666f72206b65796c656e3d626c6f636b6c656e"), + ByteUtils.HexToByteArray("53616d706c65206d65737361676520666f72206b65796c656e3e626c6f636b6c656e"), + ByteUtils.HexToByteArray("53616d706c65206d65737361676520666f72206b65796c656e3c626c6f636b6c656e2c2077697468207472756e636174656420746167"), + }; + + private static readonly byte[][] s_testMacs = new byte[][] + { + null, + ByteUtils.HexToByteArray( + "4efd629d6c71bf86162658f29943b1c308ce27cdfa6db0d9c3ce81763f9cbce5" + + "f7ebe9868031db1a8f8eb7b6b95e5c5e3f657a8996c86a2f6527e307f0213196"), + ByteUtils.HexToByteArray( + "544e257ea2a3e5ea19a590e6a24b724ce6327757723fe2751b75bf007d80f6b3" + + "60744bf1b7a88ea585f9765b47911976d3191cf83c039f5ffab0d29cc9d9b6da"), + ByteUtils.HexToByteArray( + "5f464f5e5b7848e3885e49b2c385f0694985d0e38966242dc4a5fe3fea4b37d4" + + "6b65ceced5dcf59438dd840bab22269f0ba7febdb9fcf74602a35666b2a32915"), + ByteUtils.HexToByteArray("7bb06d859257b25ce73ca700df34c5cbef5c898bac91029e0b27975d4e526a08"), // Truncated + }; + + + public HmacSha3_512Tests() : base(s_testKeys, s_testData, s_testMacs) + { + } + + [ConditionalTheory(nameof(IsSupported))] + [MemberData(nameof(TestCaseIds))] + public void HmacSha3_512_VerifyTestCases(int caseId) + { + VerifyHmac(caseId, s_testMacs[caseId]); + } + + public static IEnumerable TestCaseIds + { + get + { + for (int i = 1; i < s_testKeys.Length; i++) + { + yield return new object[] { i }; + } + } + } + + [ConditionalFact(nameof(IsSupported))] + public void HmacSha3_512_Rfc2104_2() + { + VerifyHmacRfc2104_2(); + } + + [ConditionalFact(nameof(IsSupported))] + public void HmacSha3_512_ThrowsArgumentNullForNullConstructorKey() + { + AssertExtensions.Throws("key", () => new HMACSHA3_512(null)); + } + + [ConditionalFact(nameof(IsSupported))] + public void HmacSha3_512_EmptyKey() + { + VerifyRepeating( + input: "Crypto is fun!", + 1, + hexKey: "", + output: "8F1658BB962C7048A50BEA174FA7697596F3F5F127228EEA64589DFFB0C1A07C" + + "98792648C97886B3DD9E63AB962581C67DA5EE04F2B15263555B1796782CB556"); + } + + [ConditionalFact(nameof(IsSupported))] + public void HmacSha3_512_Stream_MultipleOf4096() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl sha3-512 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "0102030405060708", + 1024, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "43A635D00606EFB4797B0B50B3C2CCAACDC8C2DA38D1369EA49CDD93EDE27824" + + "317D9014C429DB18E5A6BFD811F7B484922471085F17ED31F6A7EB4E07BFFA97"); + } + + [ConditionalFact(nameof(IsSupported))] + public void HmacSha3_512_Stream_NotMultipleOf4096() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl sha3-512 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "0102030405060708", + 1025, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "90D378A7546A66804E6C0ADF3203D3836244FD8CF628294E7F3AD95539EDF6D9" + + "E86DECE850D50DE76386CB293FA832778C7D6607A4F00AD666DA3EFFD6143E70"); + } + + [ConditionalFact(nameof(IsSupported))] + public void HmacSha3_512_Stream_Empty() + { + // Verfied with: + // echo -n "" | openssl sha3-512 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + VerifyRepeating( + input: "", + 0, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "908D1BE1A2CC5CC4B8C62E98D09AB6E967529FCB24F4177CB94CB072F5968D01" + + "CA58633748DC80D4615E3D21228BB3A5F535FA1CB963DF463CC28ABAF1A9B2D1"); + } + + [ConditionalFact(nameof(IsSupported))] + public async Task HmacSha3_512_Stream_MultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl sha3-512 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "0102030405060708", + 1024, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "43A635D00606EFB4797B0B50B3C2CCAACDC8C2DA38D1369EA49CDD93EDE27824" + + "317D9014C429DB18E5A6BFD811F7B484922471085F17ED31F6A7EB4E07BFFA97"); + } + + [ConditionalFact(nameof(IsSupported))] + public async Task HmacSha3_512_Stream_NotMultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl sha3-512 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "0102030405060708", + 1025, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "90D378A7546A66804E6C0ADF3203D3836244FD8CF628294E7F3AD95539EDF6D9" + + "E86DECE850D50DE76386CB293FA832778C7D6607A4F00AD666DA3EFFD6143E70"); + } + + [ConditionalFact(nameof(IsSupported))] + public async Task HmacSha3_512_Stream_Empty_Async() + { + // Verfied with: + // echo -n "" | openssl sha3-512 -hex -mac HMAC -macopt hexkey:000102030405060708090A0B0C0D0E0F + await VerifyRepeatingAsync( + input: "", + 0, + hexKey: "000102030405060708090A0B0C0D0E0F", + output: "908D1BE1A2CC5CC4B8C62E98D09AB6E967529FCB24F4177CB94CB072F5968D01" + + "CA58633748DC80D4615E3D21228BB3A5F535FA1CB963DF463CC28ABAF1A9B2D1"); + } + + [Fact] + public void HmacSha3_256_HashSizes() + { + Assert.Equal(512, HMACSHA3_512.HashSizeInBits); + Assert.Equal(64, HMACSHA3_512.HashSizeInBytes); + } + + [Fact] + public void HmacSha3_512_IsSupported_AgreesWithPlatformVersion() + { + Assert.Equal(PlatformDetection.SupportsSha3, HMACSHA3_512.IsSupported); + } + } +} diff --git a/src/libraries/System.Security.Cryptography/tests/HmacSha512Tests.cs b/src/libraries/System.Security.Cryptography/tests/HmacSha512Tests.cs index 44aec88b8e1e2d..3568b40353af57 100644 --- a/src/libraries/System.Security.Cryptography/tests/HmacSha512Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/HmacSha512Tests.cs @@ -9,12 +9,19 @@ namespace System.Security.Cryptography.Tests { - public class HmacSha512Tests : Rfc4231HmacTests + public class HmacSha512Tests : Rfc4231HmacTests { + public sealed class Traits : IHmacTrait + { + public static bool IsSupported => true; + public static int HashSizeInBytes => HMACSHA512.HashSizeInBytes; + } + protected override int BlockSize => 128; protected override int MacSize => HMACSHA512.HashSizeInBytes; protected override HMAC Create() => new HMACSHA512(); + protected override HMAC Create(byte[] key) => new HMACSHA512(key); protected override HashAlgorithm CreateHashAlgorithm() => SHA512.Create(); protected override byte[] HashDataOneShot(byte[] key, byte[] source) => HMACSHA512.HashData(key, source); @@ -218,5 +225,12 @@ await VerifyRepeatingAsync( hexKey: "000102030405060708090A0B0C0D0E0F", output: "2FEC800CA276C44985A35AEC92067E5E53A1BB80A6FDAB1D9C97D54068118F30AD4C33717466D372EA00BBF126E5B79C6F7143DD36C31F72028330E92AE3A359"); } + + [Fact] + public void HmacSha512_HashSizes() + { + Assert.Equal(512, HMACSHA512.HashSizeInBits); + Assert.Equal(64, HMACSHA512.HashSizeInBytes); + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/HmacTests.cs b/src/libraries/System.Security.Cryptography/tests/HmacTests.cs index 436f407c8b81b2..c6bd7ee994f3f5 100644 --- a/src/libraries/System.Security.Cryptography/tests/HmacTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/HmacTests.cs @@ -9,8 +9,11 @@ namespace System.Security.Cryptography.Tests { - public abstract class HmacTests + public abstract class HmacTests where THmacTrait : IHmacTrait { + public static bool IsSupported => THmacTrait.IsSupported; + public static bool IsNotSupported => !IsSupported; + // RFC2202 defines the test vectors for HMACMD5 and HMACSHA1 // RFC4231 defines the test vectors for HMACSHA{224,256,384,512} // They share the same datasets for cases 1-5, but cases 6 and 7 differ. @@ -26,6 +29,7 @@ protected HmacTests(byte[][] testKeys, byte[][] testData, byte[][] testMacs) } protected abstract HMAC Create(); + protected abstract HMAC Create(byte[] key); protected abstract HashAlgorithm CreateHashAlgorithm(); protected abstract byte[] HashDataOneShot(byte[] key, byte[] source); @@ -254,7 +258,7 @@ protected void VerifyHmacRfc2104_2() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void InvalidInput_Null() { using (HMAC hash = Create()) @@ -265,7 +269,7 @@ public void InvalidInput_Null() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void InvalidInput_NegativeOffset() { using (HMAC hash = Create()) @@ -274,7 +278,7 @@ public void InvalidInput_NegativeOffset() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void InvalidInput_NegativeCount() { using (HMAC hash = Create()) @@ -283,7 +287,7 @@ public void InvalidInput_NegativeCount() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void InvalidInput_TooBigOffset() { using (HMAC hash = Create()) @@ -292,7 +296,7 @@ public void InvalidInput_TooBigOffset() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void InvalidInput_TooBigCount() { byte[] nonEmpty = new byte[53]; @@ -306,7 +310,7 @@ public void InvalidInput_TooBigCount() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void BoundaryCondition_Count0() { byte[] nonEmpty = new byte[53]; @@ -332,7 +336,7 @@ public void BoundaryCondition_Count0() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void OffsetAndCountRespected() { byte[] dataA = { 1, 1, 2, 3, 5, 8 }; @@ -349,7 +353,7 @@ public void OffsetAndCountRespected() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void InvalidKey_ThrowArgumentNullException() { using (HMAC hash = Create()) @@ -358,21 +362,21 @@ public void InvalidKey_ThrowArgumentNullException() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void OneShot_NullKey_ArgumentNullException() { AssertExtensions.Throws("key", () => HashDataOneShot(key: (byte[])null, source: Array.Empty())); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void OneShot_NullSource_ArgumentNullException() { AssertExtensions.Throws("source", () => HashDataOneShot(key: Array.Empty(), source: (byte[])null)); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void OneShot_ExistingBuffer_TooSmall() { byte[] buffer = new byte[MacSize - 1]; @@ -385,7 +389,7 @@ public void OneShot_ExistingBuffer_TooSmall() AssertExtensions.FilledWith(0, buffer); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void OneShot_TryExistingBuffer_TooSmall() { byte[] buffer = new byte[MacSize - 1]; @@ -397,10 +401,10 @@ public void OneShot_TryExistingBuffer_TooSmall() AssertExtensions.FilledWith(0, buffer); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void OneShot_TryExistingBuffer_Exact() { - for (int caseId = 1; caseId <= 7; caseId++) + for (int caseId = 1; caseId < _testKeys.Length; caseId++) { byte[] buffer = new byte[MacSize]; byte[] key = _testKeys[caseId]; @@ -415,10 +419,10 @@ public void OneShot_TryExistingBuffer_Exact() } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void OneShot_TryExistingBuffer_Larger() { - for (int caseId = 1; caseId <= 7; caseId++) + for (int caseId = 1; caseId < _testKeys.Length; caseId++) { Span buffer = new byte[MacSize + 20]; byte[] key = _testKeys[caseId]; @@ -438,14 +442,14 @@ public void OneShot_TryExistingBuffer_Larger() } } - [Theory] + [ConditionalTheory(nameof(IsSupported))] [InlineData(0, 10)] [InlineData(10, 10)] [InlineData(10, 0)] [InlineData(10, 20)] public void OneShot_TryExistingBuffer_OverlapsKey(int keyOffset, int bufferOffset) { - for (int caseId = 1; caseId <= 7; caseId++) + for (int caseId = 1; caseId < _testKeys.Length; caseId++) { byte[] key = _testKeys[caseId]; byte[] data = _testData[caseId]; @@ -464,14 +468,14 @@ public void OneShot_TryExistingBuffer_OverlapsKey(int keyOffset, int bufferOffse } } - [Theory] + [ConditionalTheory(nameof(IsSupported))] [InlineData(0, 10)] [InlineData(10, 10)] [InlineData(10, 0)] [InlineData(10, 20)] public void OneShot_TryExistingBuffer_OverlapsSource(int sourceOffset, int bufferOffset) { - for (int caseId = 1; caseId <= 7; caseId++) + for (int caseId = 1; caseId < _testKeys.Length; caseId++) { byte[] key = _testKeys[caseId]; byte[] data = _testData[caseId]; @@ -490,7 +494,7 @@ public void OneShot_TryExistingBuffer_OverlapsSource(int sourceOffset, int buffe } } - [Theory] + [ConditionalTheory(nameof(IsSupported))] [InlineData(new byte[0], new byte[] { 1 })] [InlineData(new byte[] { 1 }, new byte[0])] public void OneShot_Empty_Matches_Instances(byte[] key, byte[] source) @@ -505,7 +509,7 @@ public void OneShot_Empty_Matches_Instances(byte[] key, byte[] source) } } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void HashData_Stream_Source_Null() { AssertExtensions.Throws( @@ -517,7 +521,7 @@ public void HashData_Stream_Source_Null() () => HashDataOneShot(Array.Empty(), (Stream)null)); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void HashData_Stream_Source_Null_Async() { AssertExtensions.Throws( @@ -529,7 +533,7 @@ public void HashData_Stream_Source_Null_Async() () => HashDataOneShotAsync(Array.Empty(), (Stream)null, default)); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void HashData_Stream_ByteKey_Null() { AssertExtensions.Throws( @@ -537,7 +541,7 @@ public void HashData_Stream_ByteKey_Null() () => HashDataOneShot((byte[])null, Stream.Null)); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void HashData_Stream_ByteKey_Null_Async() { AssertExtensions.Throws( @@ -545,7 +549,7 @@ public void HashData_Stream_ByteKey_Null_Async() () => HashDataOneShotAsync((byte[])null, Stream.Null, default)); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void HashData_Stream_DestinationTooSmall() { byte[] destination = new byte[MacSize - 1]; @@ -561,7 +565,7 @@ public void HashData_Stream_DestinationTooSmall() AssertExtensions.FilledWith(0, destination); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void HashData_Stream_DestinationTooSmall_Async() { byte[] destination = new byte[MacSize - 1]; @@ -577,7 +581,7 @@ public void HashData_Stream_DestinationTooSmall_Async() AssertExtensions.FilledWith(0, destination); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void HashData_Stream_NotReadable() { AssertExtensions.Throws( @@ -589,7 +593,7 @@ public void HashData_Stream_NotReadable() () => HashDataOneShot(ReadOnlySpan.Empty, UntouchableStream.Instance)); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void HashData_Stream_Cancelled() { Memory buffer = new byte[512 / 8]; @@ -603,12 +607,43 @@ public void HashData_Stream_Cancelled() AssertExtensions.FilledWith(0, buffer.Span); } - [Fact] + [ConditionalFact(nameof(IsSupported))] public void HashData_Stream_Allocating_Cancelled() { CancellationToken cancelledToken = new CancellationToken(canceled: true); ValueTask waitable = HashDataOneShotAsync(ReadOnlyMemory.Empty, Stream.Null, cancelledToken); Assert.True(waitable.IsCanceled, nameof(waitable.IsCanceled)); } + + [ConditionalFact(nameof(IsNotSupported))] + public void Ctor_NotSupported() + { + Assert.Throws(() => Create()); + Assert.Throws(() => Create(new byte[42])); + } + + [ConditionalFact(nameof(IsNotSupported))] + public async Task HashData_NotSupported() + { + byte[] key = new byte[1]; + byte[] buffer = new byte[THmacTrait.HashSizeInBytes]; + Assert.Throws(() => HashDataOneShot(key, Array.Empty())); + Assert.Throws(() => HashDataOneShot(key, ReadOnlySpan.Empty)); + Assert.Throws(() => HashDataOneShot(key, ReadOnlySpan.Empty, buffer)); + Assert.Throws(() => TryHashDataOneShot(key, ReadOnlySpan.Empty, buffer, out _)); + + Assert.Throws(() => HashDataOneShot(key, Stream.Null)); + Assert.Throws(() => HashDataOneShot(key, Stream.Null, buffer)); + await Assert.ThrowsAsync(async () => + await HashDataOneShotAsync(key, Stream.Null, default(CancellationToken))); + await Assert.ThrowsAsync(async () => + await HashDataOneShotAsync(key, Stream.Null, buffer, default(CancellationToken))); + } + } + + public interface IHmacTrait + { + static abstract bool IsSupported { get; } + static abstract int HashSizeInBytes { get; } } } diff --git a/src/libraries/System.Security.Cryptography/tests/IncrementalHashTests.cs b/src/libraries/System.Security.Cryptography/tests/IncrementalHashTests.cs index 400b8aa57834c0..dc7c33debfa8cd 100644 --- a/src/libraries/System.Security.Cryptography/tests/IncrementalHashTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/IncrementalHashTests.cs @@ -25,6 +25,13 @@ public static IEnumerable GetHashAlgorithms() yield return new object[] { SHA256.Create(), HashAlgorithmName.SHA256 }; yield return new object[] { SHA384.Create(), HashAlgorithmName.SHA384 }; yield return new object[] { SHA512.Create(), HashAlgorithmName.SHA512 }; + + if (PlatformDetection.SupportsSha3) + { + yield return new object[] { SHA3_256.Create(), HashAlgorithmName.SHA3_256 }; + yield return new object[] { SHA3_384.Create(), HashAlgorithmName.SHA3_384 }; + yield return new object[] { SHA3_512.Create(), HashAlgorithmName.SHA3_512 }; + } } public static IEnumerable GetHMACs() @@ -33,10 +40,18 @@ public static IEnumerable GetHMACs() { yield return new object[] { new HMACMD5(), HashAlgorithmName.MD5 }; } + yield return new object[] { new HMACSHA1(), HashAlgorithmName.SHA1 }; yield return new object[] { new HMACSHA256(), HashAlgorithmName.SHA256 }; yield return new object[] { new HMACSHA384(), HashAlgorithmName.SHA384 }; yield return new object[] { new HMACSHA512(), HashAlgorithmName.SHA512 }; + + if (PlatformDetection.SupportsSha3) + { + yield return new object[] { new HMACSHA3_256(), HashAlgorithmName.SHA3_256 }; + yield return new object[] { new HMACSHA3_384(), HashAlgorithmName.SHA3_384 }; + yield return new object[] { new HMACSHA3_512(), HashAlgorithmName.SHA3_512 }; + } } [Fact] @@ -298,6 +313,22 @@ public static void UnknownHmacAlgorithm() () => IncrementalHash.CreateHMAC(new HashAlgorithmName("SHA0"), Array.Empty())); } + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.DoesNotSupportSha3))] + [InlineData("SHA3-256")] + [InlineData("SHA3-384")] + [InlineData("SHA3-512")] + public static void UnsupportedAlgorithms(string algorithmName) + { + Assert.Throws(() => + IncrementalHash.CreateHMAC(new HashAlgorithmName(algorithmName), ReadOnlySpan.Empty)); + + Assert.Throws(() => + IncrementalHash.CreateHMAC(new HashAlgorithmName(algorithmName), Array.Empty())); + + Assert.Throws(() => + IncrementalHash.CreateHash(new HashAlgorithmName(algorithmName))); + } + [Theory] [MemberData(nameof(GetHashAlgorithms))] public static void VerifyIncrementalHash_Span(HashAlgorithm referenceAlgorithm, HashAlgorithmName hashAlgorithm) diff --git a/src/libraries/System.Security.Cryptography/tests/MD5Tests.cs b/src/libraries/System.Security.Cryptography/tests/MD5Tests.cs index 26ab965bf4799f..15919e84d7a91d 100644 --- a/src/libraries/System.Security.Cryptography/tests/MD5Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/MD5Tests.cs @@ -9,8 +9,14 @@ namespace System.Security.Cryptography.Tests { [SkipOnPlatform(TestPlatforms.Browser, "Not supported on Browser")] - public class MD5Tests : HashAlgorithmTestDriver + public class MD5Tests : HashAlgorithmTestDriver { + public sealed class Traits : IHashTrait + { + public static bool IsSupported => true; + public static int HashSizeInBytes => MD5.HashSizeInBytes; + } + protected override HashAlgorithm Create() { return MD5.Create(); @@ -148,5 +154,12 @@ public async Task MD5_Rfc1321_7_AsStream_Async() { await VerifyRepeatingAsync("1234567890", 8, "57edf4a22be3c955ac49da2e2107b67a"); } + + [Fact] + public void MD5_HashSizes() + { + Assert.Equal(128, MD5.HashSizeInBits); + Assert.Equal(16, MD5.HashSizeInBytes); + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/ReusabilityTests.cs b/src/libraries/System.Security.Cryptography/tests/ReusabilityTests.cs index 29571d3beb812b..4930f5c4cfcd51 100644 --- a/src/libraries/System.Security.Cryptography/tests/ReusabilityTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/ReusabilityTests.cs @@ -37,6 +37,17 @@ public static IEnumerable ReusabilityHashAlgorithms() yield return new object[] { new HMACSHA256(), }; yield return new object[] { new HMACSHA384(), }; yield return new object[] { new HMACSHA512(), }; + + if (PlatformDetection.SupportsSha3) + { + yield return new object[] { SHA3_256.Create() }; + yield return new object[] { SHA3_384.Create() }; + yield return new object[] { SHA3_512.Create() }; + + yield return new object[] { new HMACSHA3_256() }; + yield return new object[] { new HMACSHA3_384() }; + yield return new object[] { new HMACSHA3_512() }; + } } } } diff --git a/src/libraries/System.Security.Cryptography/tests/Rfc2202HmacTests.cs b/src/libraries/System.Security.Cryptography/tests/Rfc2202HmacTests.cs index e4bcc0a66667a2..f40e8638086159 100644 --- a/src/libraries/System.Security.Cryptography/tests/Rfc2202HmacTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Rfc2202HmacTests.cs @@ -6,7 +6,7 @@ namespace System.Security.Cryptography.Tests { - public abstract class Rfc2202HmacTests : HmacTests + public abstract class Rfc2202HmacTests : HmacTests where THmacTrait : IHmacTrait { private static readonly byte[][] s_testData2202 = { diff --git a/src/libraries/System.Security.Cryptography/tests/Rfc2898OneShotTests.cs b/src/libraries/System.Security.Cryptography/tests/Rfc2898OneShotTests.cs index df32356190fd49..a5dbee9dc2259b 100644 --- a/src/libraries/System.Security.Cryptography/tests/Rfc2898OneShotTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Rfc2898OneShotTests.cs @@ -281,6 +281,17 @@ public static void Pbkdf2_Rfc6070(string password, string salt, int iterations, Assert.Equal(expected, actual); } + [Theory] + [MemberData(nameof(Pbkdf2_OpenSsl_Vectors))] + public static void Pbkdf2_OpenSsl(string hashAlgorithm, string password, string salt, int iterations, string expectedHex) + { + HashAlgorithmName hashAlgorithmName = new HashAlgorithmName(hashAlgorithm); + byte[] expected = expectedHex.HexToByteArray(); + byte[] saltBytes = Encoding.UTF8.GetBytes(salt); + byte[] actual = Rfc2898DeriveBytes.Pbkdf2(password, saltBytes, iterations, hashAlgorithmName, expected.Length); + Assert.Equal(expected, actual); + } + [Fact] [OuterLoop("Uses a high number of iterations that can take over 20 seconds on some machines")] public static void Pbkdf2_Rfc6070_HighIterations() @@ -293,6 +304,17 @@ public static void Pbkdf2_Rfc6070_HighIterations() Assert.Equal(expected, actual); } + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.DoesNotSupportSha3))] + [InlineData("SHA3-256")] + [InlineData("SHA3-384")] + [InlineData("SHA3-512")] + public static void UnsupportedPkbdf2Algorithms(string hashAlgorithm) + { + HashAlgorithmName hashAlgorithmName = new HashAlgorithmName(hashAlgorithm); + Assert.Throws(() => + Rfc2898DeriveBytes.Pbkdf2(s_passwordBytes, s_salt, iterations: 1, hashAlgorithmName, s_extractLength)); + } + public static IEnumerable Pbkdf2_PasswordBytes_Compare_Data() { string largeInputHex = new string('A', 8192); // 8192 hex characters = 4096 bytes. @@ -323,6 +345,30 @@ public static IEnumerable Pbkdf2_PasswordBytes_Compare_Data() yield return new object[] { HashAlgorithmName.SHA384.Name, 257, 257, password.ByteArrayToHex(), "0000000000000000" }; yield return new object[] { HashAlgorithmName.SHA512.Name, 257, 257, password.ByteArrayToHex(), "0000000000000000" }; } + + if (PlatformDetection.SupportsSha3) + { + // Test around HMAC SHA3_256 block boundary (136) + for (int blockBoundary = 135; blockBoundary <= 137; blockBoundary++) + { + byte[] password = new byte[blockBoundary]; + yield return new object[] { HashAlgorithmName.SHA3_256.Name, 257, 257, password.ByteArrayToHex(), "0000000000000000" }; + } + + // Test around HMAC SHA3_384 block boundary (104) + for (int blockBoundary = 103; blockBoundary <= 105; blockBoundary++) + { + byte[] password = new byte[blockBoundary]; + yield return new object[] { HashAlgorithmName.SHA3_384.Name, 257, 257, password.ByteArrayToHex(), "0000000000000000" }; + } + + // Test around HMAC SHA3_512 block boundary (72) + for (int blockBoundary = 71; blockBoundary <= 73; blockBoundary++) + { + byte[] password = new byte[blockBoundary]; + yield return new object[] { HashAlgorithmName.SHA3_512.Name, 257, 257, password.ByteArrayToHex(), "0000000000000000" }; + } + } } public static IEnumerable Pbkdf2_PasswordString_Compare_Data() @@ -352,12 +398,59 @@ public static IEnumerable Pbkdf2_Rfc6070_Vectors() yield return new object[] { "pass\0word", "sa\0lt", 4096, "56fa6aa75548099dcc37d7f03425e0c3" }; } - private static HashAlgorithmName[] SupportedHashAlgorithms => new [] + public static IEnumerable Pbkdf2_OpenSsl_Vectors() + { + if (!PlatformDetection.SupportsSha3) { - HashAlgorithmName.SHA1, - HashAlgorithmName.SHA256, - HashAlgorithmName.SHA384, - HashAlgorithmName.SHA512 + yield break; + } + + // Values come from https://github.com/openssl/openssl/blob/6821acbffda908ec69769ed7f110cfde57d8ca58/test/recipes/30-test_evp_data/evppbe_pbkdf2.txt + // hashAlgorithm, password, salt, iterations, expected + yield return new object[] + { + "SHA3-256", + "password", + "salt", + 4096, + "778b6e237a0f49621549ff70d218d208", + }; + + yield return new object[] + { + "SHA3-384", + "password", + "salt", + 4096, + "9a5f1e45e8b83f1b259ba72d11c59087", }; + + yield return new object[] + { + "SHA3-512", + "password", + "salt", + 4096, + "2bfaf2d5ceb6d10f5e262cd902488cfd", + }; + } + + private static IEnumerable SupportedHashAlgorithms + { + get + { + yield return HashAlgorithmName.SHA1; + yield return HashAlgorithmName.SHA256; + yield return HashAlgorithmName.SHA384; + yield return HashAlgorithmName.SHA512; + + if (PlatformDetection.SupportsSha3) + { + yield return HashAlgorithmName.SHA3_256; + yield return HashAlgorithmName.SHA3_384; + yield return HashAlgorithmName.SHA3_512; + } + } + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/Rfc2898Tests.cs b/src/libraries/System.Security.Cryptography/tests/Rfc2898Tests.cs index 4ac54e571a52d0..4342bebb14072d 100644 --- a/src/libraries/System.Security.Cryptography/tests/Rfc2898Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Rfc2898Tests.cs @@ -361,14 +361,9 @@ public static void GetBytes_KnownValues_WithAlgorithm(KnownValuesTestCase testCa } [Theory] - [InlineData("SHA1")] - [InlineData("SHA256")] - [InlineData("SHA384")] - [InlineData("SHA512")] - public static void CheckHashAlgorithmValue(string hashAlgorithmName) + [MemberData(nameof(HashAlgorithmNames))] + public static void CheckHashAlgorithmValue(HashAlgorithmName hashAlgorithm) { - HashAlgorithmName hashAlgorithm = new HashAlgorithmName(hashAlgorithmName); - using (var pbkdf2 = new Rfc2898DeriveBytes(TestPassword, s_testSalt, DefaultIterationCount, hashAlgorithm)) { Assert.Equal(hashAlgorithm, pbkdf2.HashAlgorithm); @@ -465,6 +460,24 @@ public static IEnumerable KnownValuesTestCases() } } + public static IEnumerable HashAlgorithmNames + { + get + { + yield return new object[] { HashAlgorithmName.SHA1 }; + yield return new object[] { HashAlgorithmName.SHA256 }; + yield return new object[] { HashAlgorithmName.SHA384 }; + yield return new object[] { HashAlgorithmName.SHA512 }; + + if (PlatformDetection.SupportsSha3) + { + yield return new object[] { HashAlgorithmName.SHA3_256 }; + yield return new object[] { HashAlgorithmName.SHA3_384 }; + yield return new object[] { HashAlgorithmName.SHA3_512 }; + } + } + } + private static IEnumerable GetKnownValuesTestCases() { Encoding ascii = Encoding.ASCII; @@ -607,6 +620,42 @@ private static IEnumerable GetKnownValuesTestCases() IterationCount = 1, AnswerHex = "1E437A1C79D75BE61E91141DAE20", }; + + if (PlatformDetection.SupportsSha3) + { + // https://github.com/openssl/openssl/blob/6821acbffda908ec69769ed7f110cfde57d8ca58/test/recipes/30-test_evp_data/evppbe_pbkdf2.txt#L128-L133 + yield return new KnownValuesTestCase + { + CaseName = "OpenSSL SHA3-256", + HashAlgorithmName = "SHA3-256", + Password = "password", + Salt = "salt"u8.ToArray(), + IterationCount = 4096, + AnswerHex = "778B6E237A0F49621549FF70D218D208", + }; + + // https://github.com/openssl/openssl/blob/6821acbffda908ec69769ed7f110cfde57d8ca58/test/recipes/30-test_evp_data/evppbe_pbkdf2.txt#L135-L140 + yield return new KnownValuesTestCase + { + CaseName = "OpenSSL SHA3-384", + HashAlgorithmName = "SHA3-384", + Password = "password", + Salt = "salt"u8.ToArray(), + IterationCount = 4096, + AnswerHex = "9A5F1E45E8B83F1B259BA72D11C59087", + }; + + // https://github.com/openssl/openssl/blob/6821acbffda908ec69769ed7f110cfde57d8ca58/test/recipes/30-test_evp_data/evppbe_pbkdf2.txt#L142-L147 + yield return new KnownValuesTestCase + { + CaseName = "OpenSSL SHA3-512", + HashAlgorithmName = "SHA3-512", + Password = "password", + Salt = "salt"u8.ToArray(), + IterationCount = 4096, + AnswerHex = "2BFAF2D5CEB6D10F5E262CD902488CFD", + }; + } } public class KnownValuesTestCase diff --git a/src/libraries/System.Security.Cryptography/tests/Rfc4231HmacTests.cs b/src/libraries/System.Security.Cryptography/tests/Rfc4231HmacTests.cs index 2dd668a288ffd8..dedc5f526311db 100644 --- a/src/libraries/System.Security.Cryptography/tests/Rfc4231HmacTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Rfc4231HmacTests.cs @@ -6,7 +6,7 @@ namespace System.Security.Cryptography.Tests { - public abstract class Rfc4231HmacTests : HmacTests + public abstract class Rfc4231HmacTests : HmacTests where THmacTrait : IHmacTrait { private static readonly byte[][] s_testKeys4231 = { diff --git a/src/libraries/System.Security.Cryptography/tests/Sha1Tests.cs b/src/libraries/System.Security.Cryptography/tests/Sha1Tests.cs index 46f0f24534348f..61cd278e4a02a8 100644 --- a/src/libraries/System.Security.Cryptography/tests/Sha1Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Sha1Tests.cs @@ -8,8 +8,14 @@ namespace System.Security.Cryptography.Tests { - public class Sha1Tests : HashAlgorithmTestDriver + public class Sha1Tests : HashAlgorithmTestDriver { + public sealed class Traits : IHashTrait + { + public static bool IsSupported => true; + public static int HashSizeInBytes => SHA1.HashSizeInBytes; + } + protected override HashAlgorithm Create() { return SHA1.Create(); @@ -131,5 +137,12 @@ public async Task Sha1_Rfc3174_4_Async() { await VerifyRepeatingAsync("0123456701234567012345670123456701234567012345670123456701234567", 10, "DEA356A2CDDD90C7A7ECEDC5EBB563934F460452"); } + + [Fact] + public void Sha1_HashSizes() + { + Assert.Equal(160, SHA1.HashSizeInBits); + Assert.Equal(20, SHA1.HashSizeInBytes); + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/Sha256Tests.cs b/src/libraries/System.Security.Cryptography/tests/Sha256Tests.cs index 4abad52b940941..9d1745fe9442b9 100644 --- a/src/libraries/System.Security.Cryptography/tests/Sha256Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Sha256Tests.cs @@ -8,8 +8,14 @@ namespace System.Security.Cryptography.Tests { - public class Sha256Tests : HashAlgorithmTestDriver + public class Sha256Tests : HashAlgorithmTestDriver { + public sealed class Traits : IHashTrait + { + public static bool IsSupported => true; + public static int HashSizeInBytes => SHA256.HashSizeInBytes; + } + protected override HashAlgorithm Create() { return SHA256.Create(); @@ -146,5 +152,12 @@ await VerifyRepeatingAsync( 1000000, "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"); } + + [Fact] + public void Sha256_HashSizes() + { + Assert.Equal(256, SHA256.HashSizeInBits); + Assert.Equal(32, SHA256.HashSizeInBytes); + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/Sha384Tests.cs b/src/libraries/System.Security.Cryptography/tests/Sha384Tests.cs index c7cfea805683c7..4f14559b4b93af 100644 --- a/src/libraries/System.Security.Cryptography/tests/Sha384Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Sha384Tests.cs @@ -8,8 +8,14 @@ namespace System.Security.Cryptography.Tests { - public class Sha384Tests : HashAlgorithmTestDriver + public class Sha384Tests : HashAlgorithmTestDriver { + public sealed class Traits : IHashTrait + { + public static bool IsSupported => true; + public static int HashSizeInBytes => SHA384.HashSizeInBytes; + } + protected override HashAlgorithm Create() { return SHA384.Create(); @@ -134,5 +140,12 @@ public void Sha384_NistShaAll_2() "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", "09330C33F71147E83D192FC782CD1B4753111B173B3B05D22FA08086E3B0F712FCC7C71A557E2DB966C3E9FA91746039"); } + + [Fact] + public void Sha384_HashSizes() + { + Assert.Equal(384, SHA384.HashSizeInBits); + Assert.Equal(48, SHA384.HashSizeInBytes); + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/Sha3_256Tests.cs b/src/libraries/System.Security.Cryptography/tests/Sha3_256Tests.cs new file mode 100644 index 00000000000000..04debe723873de --- /dev/null +++ b/src/libraries/System.Security.Cryptography/tests/Sha3_256Tests.cs @@ -0,0 +1,317 @@ +// 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.IO; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace System.Security.Cryptography.Tests +{ + public class Sha3_256Tests : HashAlgorithmTestDriver + { + public sealed class Traits : IHashTrait + { + public static bool IsSupported => SHA3_256.IsSupported; + public static int HashSizeInBytes => SHA3_256.HashSizeInBytes; + } + + protected override HashAlgorithm Create() + { + return SHA3_256.Create(); + } + + protected override bool TryHashData(ReadOnlySpan source, Span destination, out int bytesWritten) + { + return SHA3_256.TryHashData(source, destination, out bytesWritten); + } + + protected override byte[] HashData(byte[] source) => SHA3_256.HashData(source); + + protected override byte[] HashData(ReadOnlySpan source) => SHA3_256.HashData(source); + + protected override int HashData(ReadOnlySpan source, Span destination) => + SHA3_256.HashData(source, destination); + + protected override int HashData(Stream source, Span destination) => + SHA3_256.HashData(source, destination); + + protected override byte[] HashData(Stream source) => SHA3_256.HashData(source); + + protected override ValueTask HashDataAsync(Stream source, Memory destination, CancellationToken cancellationToken) => + SHA3_256.HashDataAsync(source, destination, cancellationToken); + + protected override ValueTask HashDataAsync(Stream source, CancellationToken cancellationToken) => + SHA3_256.HashDataAsync(source, cancellationToken); + + [ConditionalFact(nameof(IsSupported))] + public void SHA3_256_Kats() + { + foreach ((string Msg, string MD) kat in Fips202Kats) + { + Verify(Convert.FromHexString(kat.Msg), kat.MD); + } + } + + [ConditionalFact(nameof(IsSupported))] + public void SHA3_256_Empty_Stream() + { + VerifyRepeating("", 0, "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"); + } + + [ConditionalFact(nameof(IsSupported))] + public async Task SHA3_256_Empty_Stream_Async() + { + await VerifyRepeatingAsync("", 0, "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"); + } + + [ConditionalFact(nameof(IsSupported))] + public void SHA3_256_VerifyLargeStream_MultipleOf4096() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl dgst -sha3-256 + VerifyRepeating( + "0102030405060708", + 1024, + "5e80dd4330d9124adce40a043f166d7e0f6853050fd99919c7b1436ee0a538e9"); + } + + [ConditionalFact(nameof(IsSupported))] + public void SHA3_256_VerifyLargeStream_NotMultipleOf4096() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl dgst -sha3-256 + VerifyRepeating( + "0102030405060708", + 1025, + "5dbbd15ba5745412a79835cc4bec1bede925da06eca7a5bbf50c38a6ec1c49bc"); + } + + [ConditionalFact(nameof(IsSupported))] + public async Task SHA3_256_VerifyLargeStream_NotMultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl dgst -sha3-256 + await VerifyRepeatingAsync( + "0102030405060708", + 1025, + "5dbbd15ba5745412a79835cc4bec1bede925da06eca7a5bbf50c38a6ec1c49bc"); + } + + [ConditionalFact(nameof(IsSupported))] + public async Task SHA3_256_VerifyLargeStream_MultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl dgst -sha3-256 + await VerifyRepeatingAsync( + "0102030405060708", + 1024, + "5e80dd4330d9124adce40a043f166d7e0f6853050fd99919c7b1436ee0a538e9"); + } + + [Fact] + public void SHA3_256_HashSizes() + { + Assert.Equal(256, SHA3_256.HashSizeInBits); + Assert.Equal(32, SHA3_256.HashSizeInBytes); + } + + [Fact] + public void SHA3_256_IsSupported_AgreesWithPlatformVersion() + { + Assert.Equal(PlatformDetection.SupportsSha3, SHA3_256.IsSupported); + } + + private static IEnumerable<(string Msg, string MD)> Fips202Kats + { + get + { + // Generated from SHA3_256ShortMsg.rsp + yield return (Msg: "", MD: "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a"); + yield return (Msg: "e9", MD: "f0d04dd1e6cfc29a4460d521796852f25d9ef8d28b44ee91ff5b759d72c1e6d6"); + yield return (Msg: "d477", MD: "94279e8f5ccdf6e17f292b59698ab4e614dfe696a46c46da78305fc6a3146ab7"); + yield return (Msg: "b053fa", MD: "9d0ff086cd0ec06a682c51c094dc73abdc492004292344bd41b82a60498ccfdb"); + yield return (Msg: "e7372105", MD: "3a42b68ab079f28c4ca3c752296f279006c4fe78b1eb79d989777f051e4046ae"); + yield return (Msg: "0296f2c40a", MD: "53a018937221081d09ed0497377e32a1fa724025dfdc1871fa503d545df4b40d"); + yield return (Msg: "e6fd42037f80", MD: "2294f8d3834f24aa9037c431f8c233a66a57b23fa3de10530bbb6911f6e1850f"); + yield return (Msg: "37b442385e0538", MD: "cfa55031e716bbd7a83f2157513099e229a88891bb899d9ccd317191819998f8"); + yield return (Msg: "8bca931c8a132d2f", MD: "dbb8be5dec1d715bd117b24566dc3f24f2cc0c799795d0638d9537481ef1e03e"); + yield return (Msg: "fb8dfa3a132f9813ac", MD: "fd09b3501888445ffc8c3bb95d106440ceee469415fce1474743273094306e2e"); + yield return (Msg: "71fbacdbf8541779c24a", MD: "cc4e5a216b01f987f24ab9cad5eb196e89d32ed4aac85acb727e18e40ceef00e"); + yield return (Msg: "7e8f1fd1882e4a7c49e674", MD: "79bef78c78aa71e11a3375394c2562037cd0f82a033b48a6cc932cc43358fd9e"); + yield return (Msg: "5c56a6b18c39e66e1b7a993a", MD: "b697556cb30d6df448ee38b973cb6942559de4c2567b1556240188c55ec0841c"); + yield return (Msg: "9c76ca5b6f8d1212d8e6896ad8", MD: "69dfc3a25865f3535f18b4a7bd9c0c69d78455f1fc1f4bf4e29fc82bf32818ec"); + yield return (Msg: "687ff7485b7eb51fe208f6ff9a1b", MD: "fe7e68ae3e1a91944e4d1d2146d9360e5333c099a256f3711edc372bc6eeb226"); + yield return (Msg: "4149f41be1d265e668c536b85dde41", MD: "229a7702448c640f55dafed08a52aa0b1139657ba9fc4c5eb8587e174ecd9b92"); + yield return (Msg: "d83c721ee51b060c5a41438a8221e040", MD: "b87d9e4722edd3918729ded9a6d03af8256998ee088a1ae662ef4bcaff142a96"); + yield return (Msg: "266e8cbd3e73d80df2a49cfdaf0dc39cd1", MD: "6c2de3c95900a1bcec6bd4ca780056af4acf3aa36ee640474b6e870187f59361"); + yield return (Msg: "a1d7ce5104eb25d6131bb8f66e1fb13f3523", MD: "ee9062f39720b821b88be5e64621d7e0ca026a9fe7248d78150b14bdbaa40bed"); + yield return (Msg: "d751ccd2cd65f27db539176920a70057a08a6b", MD: "7aaca80dbeb8dc3677d18b84795985463650d72f2543e0ec709c9e70b8cd7b79"); + yield return (Msg: "b32dec58865ab74614ea982efb93c08d9acb1bb0", MD: "6a12e535dbfddab6d374058d92338e760b1a211451a6c09be9b61ee22f3bb467"); + yield return (Msg: "4e0cc4f5c6dcf0e2efca1f9f129372e2dcbca57ea6", MD: "d2b7717864e9438dd02a4f8bb0203b77e2d3cd8f8ffcf9dc684e63de5ef39f0d"); + yield return (Msg: "d16d978dfbaecf2c8a04090f6eebdb421a5a711137a6", MD: "7f497913318defdc60c924b3704b65ada7ca3ba203f23fb918c6fb03d4b0c0da"); + yield return (Msg: "47249c7cb85d8f0242ab240efd164b9c8b0bd3104bba3b", MD: "435e276f06ae73aa5d5d6018f58e0f009be351eada47b677c2f7c06455f384e7"); + yield return (Msg: "cf549a383c0ac31eae870c40867eeb94fa1b6f3cac4473f2", MD: "cdfd1afa793e48fd0ee5b34dfc53fbcee43e9d2ac21515e4746475453ab3831f"); + yield return (Msg: "9b3fdf8d448680840d6284f2997d3af55ffd85f6f4b33d7f8d", MD: "25005d10e84ff97c74a589013be42fb37f68db64bdfc7626efc0dd628077493a"); + yield return (Msg: "6b22fe94be2d0b2528d9847e127eb6c7d6967e7ec8b9660e77cc", MD: "157a52b0477639b3bc179667b35c1cdfbb3eef845e4486f0f84a526e940b518c"); + yield return (Msg: "d8decafdad377904a2789551135e782e302aed8450a42cfb89600c", MD: "3ddecf5bba51643cd77ebde2141c8545f862067b209990d4cb65bfa65f4fa0c0"); + yield return (Msg: "938fe6afdbf14d1229e03576e532f078898769e20620ae2164f5abfa", MD: "9511abd13c756772b852114578ef9b96f9dc7d0f2b8dcde6ea7d1bd14c518890"); + yield return (Msg: "66eb5e7396f5b451a02f39699da4dbc50538fb10678ec39a5e28baa3c0", MD: "540acf81810a199996a612e885781308802fe460e9c638cc022e17076be8597a"); + yield return (Msg: "de98968c8bd9408bd562ac6efbca2b10f5769aacaa01365763e1b2ce8048", MD: "6b2f2547781449d4fa158180a178ef68d7056121bf8a2f2f49891afc24978521"); + yield return (Msg: "94464e8fafd82f630e6aab9aa339d981db0a372dc5c1efb177305995ae2dc0", MD: "ea7952ad759653cd47a18004ac2dbb9cf4a1e7bba8a530cf070570c711a634ea"); + yield return (Msg: "c178ce0f720a6d73c6cf1caa905ee724d5ba941c2e2628136e3aad7d853733ba", MD: "64537b87892835ff0963ef9ad5145ab4cfce5d303a0cb0415b3b03f9d16e7d6b"); + yield return (Msg: "6ef70a3a21f9f7dc41c553c9b7ef70db82ca6994ac89b3627da4f521f07e1ae263", MD: "0afe03b175a1c9489663d8a6f66d1b24aba5139b996400b8bd3d0e1a79580e4d"); + yield return (Msg: "0c4a931ff7eace5ea7cd8d2a6761940838f30e43c5d1253299abd1bd903fed1e8b36", MD: "dc5bebe05c499496a7ebfe04309cae515e3ea57c5d2a5fe2e6801243dd52c93b"); + yield return (Msg: "210f7b00bf8b4337b42450c721c3f781256359d208733846b97c0a4b7b044c38dbb219", MD: "3305c9d28e05288a2d13994d64c88d3506399cd62b2b544213cf3539a8e92e2e"); + yield return (Msg: "3cb8992759e2dc60ebb022bd8ee27f0f98039e6a9fe360373b48c7850ce113a0ff7b2ae5", MD: "3c00bf3e12ade9d2de2756506f809f147c8d6adc22e7bb666e0b1d26469e65a5"); + yield return (Msg: "22634f6ba7b4fccaa3ba4040b664dbe5a72bf394fb534e49c76ec4cdc223f4969e2d37e899", MD: "a87e5c78837d7be0060d8f5eda975489ec961b28d7088f42a70f92414ae17793"); + yield return (Msg: "6e1dcd796b2015ee6760f98fdb40e668b2cf38b05c91f6a91e83bcc8ac59f816f90a59d64e8e", MD: "746bf845c08aa186b5fe1ca35528232c4a491a3a2a32cd23e990bc603f3268ae"); + yield return (Msg: "ee0be20320f9d44073281265a6e9fa6b9d252495624b8d016b8ef57e1b4e859d8ad3b50b89416d", MD: "a3257baf14ca16e1137dc5158703f3b02ebc74fc7677165fe86d4be1f38e2f7c"); + yield return (Msg: "8ae2da242635b6568289bf6bec8a438dbac1f5b4d50a90bb7449bdb92a59378e23452dbcabbbe879", MD: "e25c44802c5cf2e9f633e683d37aa8c8db8a0e21c367808121d14d96c8a400b5"); + yield return (Msg: "bdd0252dec5b798ef20e51791a18e8ca234d9bfde632a9e5395337a112dd97cdf068c9f57615424f59", MD: "e02c1b197979c44a5a50d05ea4882c16d8205c2e3344265f8fe0e80aed06c065"); + yield return (Msg: "c4c7b6315cb60b0e6cd01ef0b65f6486fdae4b94c6be21465c3a31c416ad2f06dcf3d6eae8eecf84ca7a", MD: "2da21867cd6b5402d3caff92a05fddfca90199fd51a94a066af164ce3d36c949"); + yield return (Msg: "b17977aced3a1184b14b0e41a04dd8b513c925ca19211e1abdc6c1b987ac845545fb3b820a083b4f7883c0", MD: "f91b016d013ede8d6a2e1efd4c0dd99417da8b0222d787867ca02b0ea2e80e45"); + yield return (Msg: "f65c3aa1d9981a84e49fc86d938f3f756f60e3858d5e1f6957dd4d268e28d68e90ba9a11d7b192d6c37fb30b", MD: "3acbebf8eda9d3c99a6b6b666366c391e8200d55fd33ad8680734def1dc7ae85"); + yield return (Msg: "49abba1fa98f3c4470d5dd4ed36924af4a7ad62f4c2dd13e599238883ed7d0cb95bbaae58b460332e6b7681446", MD: "02bcd9ea4f1aa5276f38e30351a14a072bc5d53a52d04d559a65ca46f1bcb56e"); + yield return (Msg: "275645b5a2514fe65a82efac57e406f224e0259677674f1d133f00a5ee9a6d1a8fed0eadbbff5a825041d2a9715d", MD: "c70a874d786cd0f3f09fa4dc1bb8f551d45f26d77ad63de1a9fdfb3b7c09c041"); + yield return (Msg: "cd02b32107b9a640fc1bf439ac81a5c27d037c6076e1cfe6ad229638037ac1550e71cf9557c29c2fc6017afd5a8184", MD: "36c73d11d450784eb99af068cd4e1cbc5768c8a2118010aceec6d852dda80d95"); + yield return (Msg: "5a72e0e1aec82a6541f04883bb463b0c39c22b59431cfb8bfd332117a1afb5832ce5c76a58fcf6c6cb4e3e6f8e1112de", MD: "90fc3193552ec71d3315ebbb807913afd4cd2f0833a65e40d011d64de5e66513"); + yield return (Msg: "43402165911890719f9179f883bbbc2a3be77682e60dd24b356a22621c6d2e3dcdd4cb2ce613b0dfe9f58629ee853e0394", MD: "5c4b6ceac9441defa99b10b805a725d4018b74b3e1f24ad8934fc89b41b8fd9e"); + yield return (Msg: "fc56ca9a93982a4669ccaba6e3d184a19de4ce800bb643a360c14572aedb22974f0c966b859d91ad5d713b7ad99935794d22", MD: "e21806ce766bbce8b8d1b99bcf162fd154f54692351aec8e6914e1a694bda9ee"); + yield return (Msg: "ace6297e50d50a11388118efc88ef97209b11e9dfcb7ad482fc9bf7d8deecc237ad163d920c51f250306d6cedc411386a457c7", MD: "f5581403a082bbf5ad7e09bdfccc43bf9683ebc88291d71d9ce885a37e952bd6"); + yield return (Msg: "3bad18046e9424de24e12944cd992cfba4556f0b2ae88b7bd342be5cff9586092bb66fac69c529040d10dd66aa35c1023d87eb68", MD: "faed76ff5a1cd99183b311e502c54e516d70a87050cf8961c8cd46f65c1358cd"); + yield return (Msg: "e564c9a1f1aaf8545a259f52c3fd1821ed03c22fd7424a0b2ad629d5d3026ef4f27cbe06f30b991dfa54de2885f192af4dc4ddc46d", MD: "811529c600c9d780f796a29a6b3e89f8a12b3f29c36f72b06cca7edc36f48dc0"); + yield return (Msg: "6043fa6465d69cab45520af5f0fd46c81dbf677531799802629863681cea30ffa3b00836fbf49f87051d92aaeac0ed09bcb9f0755b7b", MD: "b0fceecdaef6c76d5fc3835b523ce2416f4a9b9bd1f90234445df0f2b689f2f5"); + yield return (Msg: "2040c538c79237e6f2b8188c6375ec2f610ac2301607b9c23660c3a1e1c3a902cb2950c59aac3af28f984f6369c4debe8623dfa74c967b", MD: "e33dbdc0acc23fcfad3c759c4333410bd3a40efb1366ade157d2c81d65a0a6c7"); + yield return (Msg: "00ff6c96b7aa3cf27d036cf20af7031434113252574bda9cf9244d85aef2593d3a7a83bff6be904b75164a1766828042bc3f4f090d98a03d", MD: "d000eafca34815783bed9b050c6901c97f2e77d4771a0ed724dd8f6ff1448791"); + yield return (Msg: "e8df14936cce118139e690f1662f88cfbc9c333b6dea658c02cb1d959644592842542fd9d8d61a04d4a892128f0ddff7b6502efffbabe5cb0a", MD: "3479a9617a3adca35854c08fe987c2fe7ff2b01b04f2d952c107b3f066420551"); + yield return (Msg: "4ed981a31f70dd6b70c161be1f01fc1bba54d06d9494e7eb194e213d5e0e71e0fddd49cb1f075353da22624cbe4ba871aab32906e45b6fbb691b", MD: "9c824a00e068d2fda73f9c2e7798e8d9394f57f94df0edeb132e78e8a379a0cf"); + yield return (Msg: "7802b70c6158bc26d5f157671c3f3d81ab399db552b9f851b72333770348eb1fdb8a085f924095eb9d5ccfd8474b7ba5a61c7d7bcde5a7b44362cf", MD: "fa9726ccb068c0adb5d20079c35a318b3d951eb43b196c509ab790b7e9202207"); + yield return (Msg: "ff83dcd7c1a488e5a128d5b746284552f1f2c091615d9519f459bc9010ca5e0ac19796c4a3fd7a15032a55a1410737d07855b07f61fbd8f5759e9218", MD: "8bd8d494a41acda4b7cd2994badaecff0f46ba2743458f6c3fdc0226f9492ede"); + yield return (Msg: "afd4764cc7d5de16a3cf80c51d0c0d919f18700c7dc9bc4e887d634fe0a3aa94097d590e4123b73f11ccb59e23496a3d53d2bfa908056c11c52c23abfb", MD: "e9e3b3da648cf230f1973f3814eb81316d2a496826ea39adf4674576f97e1167"); + yield return (Msg: "6fa6de509719ffbf17759f051453c0ac3cbe13346546bbc17050541074b034af197af06e41142211ee906a476039b3e07d6cb83a76aac6fca8eac307c034", MD: "766630993fbb651fd8d3603e3eebc81931fb1302a46791df259a6e13ca2cba9f"); + yield return (Msg: "93cbb7e47c8859bef939155bea488090283ecf5023d99767c960d86baa333af05aa696fc170fb8bbac1e6473956d96b964580ee6640f0cc57be9598e55fc86", MD: "d3212abca1100eb7658c0f916daf2692c57a47b772ee031c4ec6ad28a4a46de9"); + yield return (Msg: "67e384d209f1bc449fa67da6ce5fbbe84f4610129f2f0b40f7c0caea7ed5cb69be22ffb7541b2077ec1045356d9db4ee7141f7d3f84d324a5d00b33689f0cb78", MD: "9c9160268608ef09fe0bd3927d3dffa0c73499c528943e837be467b50e5c1f1e"); + yield return (Msg: "4bef1a43faacc3e38412c875360606a8115d9197d59f61a85e0b48b433db27695dc962ed75d191c4013979f401cf3a67c472c99000d3a152227db61de313ab5a1c", MD: "8703a1f7424c3535f1d4f88c9b03d194893499478969fbb0a5dc2808a069ab8f"); + yield return (Msg: "f0be5e961bb55b3a9452a536504f612a3e66aec8160a882e5156eb7278433b7ea21de31e39383d57fcdfb2fb4a8d227a9d6085fb55cad3abb78a225535da0e34efea", MD: "2fa180209bf6b4ad13c357d917fabb3e52c101a0cdb3f2299fa0f7f81dfb848e"); + yield return (Msg: "206f1c36ba25aea73398fffc9b65c4637cc1f05a6bbee014dccbd61e3b7aa9423887bbac62152a4bf73a4b7afabe54e08720589464da7985d8e6591ac081d115df2fe6", MD: "558ea7c800b687380cce7e06006e1ebe0b89973f788c4caac5780f22dbf382e8"); + yield return (Msg: "8cd71434c00663f3bda0205508a4a266548dc69e00ca91fde06d165b40279af92674f75bd8133e5a9eb9a075c9068f68f4b820008a1fb42d89d1d759859e68f8efc6fb60", MD: "085b343b08516f320a9b90fe50440a8bc51ae0850fa38d88724a4d6bd3df1ad4"); + yield return (Msg: "4cf5bbd91cac61c21102052634e99faedd6cdddcd4426b42b6a372f29a5a5f35f51ce580bb1845a3c7cfcd447d269e8caeb9b320bb731f53fe5c969a65b12f40603a685afe", MD: "f9dbb88c5bb4415e17dee9222174538eeab371b12d8d572cfdf55b806e3158e4"); + yield return (Msg: "e00e46c96dec5cb36cf4732048376657bcd1eff08ccc05df734168ae5cc07a0ad5f25081c07d098a4b285ec623407b85e53a0d8cd6999d16d3131c188befbfc9ebb10d62daf9", MD: "3571326a1577c400b967ac1c26df2a0dcf5db7070eac262a8071da16afa7c419"); + yield return (Msg: "981f41a83d8f17f71fc03f915a30cd8ac91d99aa1b49ef5c29fb88c68646b93a588debcd67474b457400c339cca028731df0b599875ab80df6f18b11b0b1c62f2a07b3d8209402", MD: "62aea8760759a996f4d855e99bcd79e9a57ea362522d9b42fd82c12c9294a217"); + yield return (Msg: "5c589fc54fefc4d6e2249a36583e1992fc6b8a9c070e8e00c45a639af22063e66ae5cdb80238c82db043a5e1f39f65626e6d7be5d6a2d3380fa212f89211200412e5e4315fc04e40", MD: "18deba74e9d93ae7df93c6c316ef201bf5e3a661e68868e14d4f56264f5d858c"); + yield return (Msg: "7c8691e7b2560fe87fcc5e2877f7e3c84d9101eca4818f6322a58986c6cf05627c0d6919ef2edc859f81fa1f33e0cc1f10edf7e52a9c33981af2ff0d720c94ea4d62170b2a4d1224fa", MD: "5a5a438b57c1b3ce8756094252362afeaa9fc91cd45b385d16994ec8af49aa6b"); + yield return (Msg: "97359b564b2bc20800ed1e5151b4d2581a0427ce9539d324c3637cfb0e5378dc2cf6d72946e2a3535a2f664ede88ed42a6814c84072b22c43de71e880a77c2d9a05b673bc15a82e3255f", MD: "be54f2e435f760d5b77c0ae61ef0aa7f5f3366f47819f350dc8a39aff8c73a8f"); + yield return (Msg: "a0dfaecd3e307c5ddf9a93603f7e19725a779218734904525b14586ff0ce0425e4efe7e1c06e745c28ed136f6031c4280fd4061d433ef700b6d1bc745064231fecf387015f94f504b6ad8c", MD: "60d80f1c703dad5da93db222fb45fb7fa768c8aa2787f4b81f1e00365b8f49e2"); + yield return (Msg: "568d66d061306c3419a1928ce7edc8e3400c30998f09bdac6f63ff351eb23d362e8dc5927eac805d694ac9563dcd7fb2efa9591c0d827af9f39146f0424873aa8e3963d65734b1713baf0a44", MD: "7a4fe37f296991121792dd7c2c30390725a1eebbf20b766a5a1c3c6c3646d996"); + yield return (Msg: "d65b9f881d1fc7f17d6dd429faca8404e6ce60fba7d89b7fba003c8ef84d8083182979327611fc341291ba80dc70ad3b2f28b6d29b988445e7fdb7c6561f45822ac81dbf677a0b27d961dc6358", MD: "51cc71b6934afcf28fa49942b76323f36cd6a0aecc5a0e49c10994ddcabdbb80"); + yield return (Msg: "711c88adf13e7a0e694652f2b9a397543f4937fafb4ccca7f1ad1d93cf74e818d0fedfaee099f019014ec9e1edfe9c03fdb11fe6492ad89011bf971a5c674461de15daff1f44b47adad308baa314", MD: "1780e52e306858478290c46b04d8068f078a7f6ad8e3790a68fc40dccfbdadc9"); + yield return (Msg: "f714a27cd2d1bc754f5e4972ab940d366a754e029b6536655d977956a2c53880332424ddf597e6866a22bfca7aa26b7d74bc4c925014c4ed37bfe37245fa42628d1c2ee75dc909edc469ee3452d894", MD: "f4afa72f3e489ad473dc247aae353da99fb005b490e2c4e1f5bd16a99732b100"); + yield return (Msg: "fe0c3280422c4ef6c82116e947da89f344d6ff997bf1aec6807e7379a695d0ba20ae31d2666f73bbdbc3a6d6ac2c12dcfb5a79173dfc9cd2e0d6000e3114f2767edec995772c6b47dadc136d500251e5", MD: "89198e2363efd4e0ba7a8a45f690f02712e6f856668517bae118d11e9a9dc7cc"); + yield return (Msg: "02e238461d0a99d49c4cd16f442edf682c39b93114fc3d79f8546a99e5ead02f0cfc45081561da44b5c70eb48340418707fd6b2614580d5c581868ba32f1ee3ac34bf6224845b32ba7f867e34700d45025", MD: "abef81b33591eedcac0cf32fb5a91c931f2d719c37801409133552170ce50dbf"); + yield return (Msg: "fb7c8cd4031007f8159d5c4c6120dee6777a3ace0a245b56f31e8aae7828dab3cf35c308de1d0d684592ef3a9e55796603a92f68d109f7a3ac1635f7c4d334955614c812753431bb0a0743291a0fc41547f3", MD: "5a67284d39e4f37caa64ca1a54593c35f6d8f3a3ec20d460393a39f6f57c4486"); + yield return (Msg: "6b2e868c7d0ee1c240d3a67e2fdf36e8e23817c02644a54453d10454da5859d41e833a5285ec63e8ce28aa64a50435a7740eea4b7d5827892678b35993d3f5da7a1c64f533173f3d0fa37e1aebf70827052c26", MD: "aecf5dab6fea9ffd1bce2cdfeec0bee9d214a669e8306d5b6688afa8957fc91f"); + yield return (Msg: "e5f3ba000c43bb6aca4e0a711a75912a48241cffa5b4b0b17f901f9e5097d94036c205f7a307d008567d05e58ac0dfaf6d971bf9d3d450cf2c7c83f6b328f676e9ab425642f5a5a71e389dc4fa49b6d7e848a09f", MD: "182d6e4316f4bc18d7163b1b21462d99f99c6f34d2c00ee771ce54fd6c5018b9"); + yield return (Msg: "939c61e68af5e2fdb75a2eebb159a85b0c87a126ce22701622f5c5ef517c3ab0ed492b1650a6c862457c685c04732198645b95f84ccb0e726a07ce132827a044dc76b34d3f19a81721f1ea365bc23e2604949bd5e8", MD: "121057b0b9a627be07dc54e7d1b719f0a3df9d20d29a03a38b5df0a51503df93"); + yield return (Msg: "9eadaf4811a604c65eaa7b1c6e89f2c0ab96bebec25a950ba78aac16d9371ca1e7458acf331e077ef6a735d68474ab22d2389bdf357fb2136c9f40e1e1eb99592c2bbb95d94931016b4d37faa08b1e9bf71bf2d3708a", MD: "c237194b902e48dca5bd096cb51562079d0cdccb2af8088197676c17b0896be2"); + yield return (Msg: "71dcca239dced2ac5cc49a9bf9ea69a99be22ba62216716b524db80f337dee5eb7e032869e4adc1497babd1fa82fa8c3cfbd30d2eadfb4c5d40f99f9d194d7182c9cb7d41e8adbdcf2917e086782fdd756e2961c944070", MD: "377d1cffb626735810b613fd31ef9bbb4577cd752521abe3a41afa921e623da0"); + yield return (Msg: "ea130d3236bca7dffb4b9e50e805309a503e7347227aeb9f1bd15c263a98dd65753d2eedaa734b9ad88f41158f32419ca529f3062b910c019f3f239f635fc1116e5ab7b242feb4471ed9168474e501d39d6bae52cc21061a", MD: "85c7a52d53f7b41162ea9f1ef0d07c3fb8f0ec621617f88cb3828ebe5388ab3d"); + yield return (Msg: "28f1be1156792af95c6f72e971bf1b64e0127b7653ff1e8c527f698907a27d1544815e38c7745529bc859260832416f2b41cd01e60c506239a7bf7553650bf70d1fe7a2c1220ac122ea1e18db27490447d8545a70bf0ffc8fa", MD: "b2eb3762a743d252567796692863b55636cb088e75527efd7306a2f6e3a48a85"); + yield return (Msg: "c8400ef09c13e8acc8a72258f5d1d20302c6e43b53250c2f6c38ff15be77e3cac04d04b8421fc8fdff8be5ca71edd108e9287b42dea338bf859100eea376da08a0e695f0dc90b95e467cbd3c2a917a504a5ae01c310ae802c4bd", MD: "69966e89b7bc7f39cd85791b92180ff3fed658d8240e393e1e6d7c24b8d0ac95"); + yield return (Msg: "a48950c961438e09f4d054ac66a498e5f1a4f6eabfde9b4bf5776182f0e43bcbce5dd436318f73fa3f92220cee1a0ff07ef132d047a530cbb47e808f90b2cc2a80dc9a1dd1ab2bb274d7a390475a6b8d97dcd4c3e26ffde6e17cf6", MD: "44c00cf622beca0fad08539ea466dcbe4476aef6b277c450ce8282fbc9a49111"); + yield return (Msg: "e543edcff8c094c0b329c8190b31c03fa86f06ace957918728692d783fa824ba4a4e1772afbe2d3f5cba701250d673405d2c38d52c52522c818947bcc0373835b198c4cc80b029d20884ac8c50893c3f565d528a0cb51bf8a197d9d6", MD: "6d5260384f3cefd3758fb900dcba3730d2b23cee03d197abeff01369dc73c180"); + yield return (Msg: "4e10ab631718aa5f6e69ee2c7e17908ec82cb81667e508f6981f3814790cfd5d112a305c91762c0bd9dd78e93ef3a64c8be77af945b74ff234a0b78f1ed962d0d68041f276d5ea40e8a63f2cab0a4a9ed3526c8c523db7cb776b9825b4", MD: "d88e5f3b2d0a698fd943233760a3000a3360d9040e7374b22e39ea58d868102d"); + yield return (Msg: "604d8842855354811cd736d95c7f46d043a194048b64bf6cda22c3e0391113dcc723e881ae2ad8dc5740aa6bda6669ddb96bb71acd10648380693f7b3d862c262553777004bd6852831618519fbb824759f4dd65af1b2a79cc01096d7c8d", MD: "8a8ab6cf5c02b9ae8f4c170740eff1592f3eda11d3420ac8b421d93cfbb35db8"); + yield return (Msg: "628180e14f41ebdfde3b4439de55ee9cd743d41040f3457ef2280370dd659619fa0ce69580c709725b275a6eda8bcb82a8447c20fdf68cba15412f83e2a10079fe9399a3e3fa61975ec0a64041c0ecde59e4844e9f8a608cb22d2576854182", MD: "8d154bf6f9cb72efc0d8b3927a8f690060d1d48bbe5cc72094d2c8b149a75132"); + yield return (Msg: "fc150b1619d5c344d615e86fca1a723f4eeb24fbe21b12facde3615a04744ef54d8a7191a4454357de35df878cb305692278648759681919d1af73c1fb0ff9783678aec838da933db0376e1629fcca3f32913f84bc2ff3ffc3f261d2312f591c", MD: "3f626c8bb20a132495bd3022b3fcd0ce0604b91a9d70132dab4099f73dde23d5"); + yield return (Msg: "6dadbecdd15e5646e3f37a6fe5b328e06113cce3c8cf07285939afba44d117321017902b3a9d2ff51f60d18e1b585dcdf34e49e170ee60fa4d1dc246548d2c1fc38e7983f42769c43d65a28016f3f4d479ebe1cd8fec5d1f886dd21aca5067d94f", MD: "9098ea34c40b541b153e80a8bd92da19432b18b7d329760b302f8a54c395dd06"); + yield return (Msg: "9cc5fd3035b72dc63b8c3c326fd013081e6b8716f526d3fe176b45256d4c37cc3dc8417dff49ada96c702b8fd715c65fc08a17a0a720b9cf1eedfd4922ccde6baba437f782ee33b95371056b0350dad743470c3b663299f16fcfd34f6fc459cd0ee4", MD: "b0c04f24bb6d3d4fcbfdf9222d0e886f1eb60a0566a478085f7623a025a5b981"); + yield return (Msg: "f3f063fbcf2d74aa5a02d240c962ed7bb119b3a212bdb41594e28428108e613152ed16e01e451fcf702b0e5a08f82eb12677652b93e05fdee00ae86cf2dc9a1fbf05b93952ec5b8515eacc324fb830e1ec236afd7d073d4b7f7ab1c2e048b99cbfa012", MD: "f930d79360b581b1bbfdeac57133a339444f5c44538c921631eabaf058277d32"); + yield return (Msg: "840739a3d6992c13ec63e6dbf46f9d6875b2bd87d8878a7b265c074e13ab17643c2de356ad4a7bfda6d3c0cc9ff381638963e46257de087bbdd5e8cc3763836b4e833a421781791dfcae9901be5805c0bbf99cca6daf574634ec2c61556f32e642730510", MD: "19795657e08cfbb247a17cf209a4905f46e4ddf58eea47feee0be9bb9f5c460f"); + yield return (Msg: "4a51b49393ab4d1b44fb6dc6628855a34e7c94d13b8b2142e5d5a7bf810e202cefdca50e3780844a33b9942f89e5c5b7dd6afb0a44541d44fb40687859780af5025fecc85e10cf8249429a3b0c6ff2d68c350c87c2fcbf936bd9de5701b2c48ce9a330c9ee", MD: "128fb4114e43eefd19277c708be9e6873e66d7fd59c58a1485b7b015facfa795"); + yield return (Msg: "afc309e6b7b74dfb0d368e3894266fc4a706c3325e21f5550d07a6560e3d9703c134ca6ad078e4a7b82ad6fa85b0bc1ddcab05d43f29d5c58d1da78ac80c37051b089ff31ce2c0c44e9ce3abea1da0f1df28008e178fdefafca493413bf1d256c729d0a9225e", MD: "03e782b01a4ba10f640470bb3cae487eb9cbbaab8c9941978b194f6a312cf79e"); + yield return (Msg: "c5ae750f2230642092397b84ad5526c46ae9480ada16892816e0f2db7690b751035653ea2f33da3cc4168b591b46a5548eff7d012f60ccfdbb854deec9f0880c472de8e127b5144c56147cccee4732fbac68fc59a48da74b33ed9e643644bbe279795c7c737eba", MD: "f64b7ab243ce6e6c04b483888ba8a655465c21d95eb60c7b8d6e566a3811bae2"); + yield return (Msg: "603e13f61499e12ec6b33b68847a281d314f54dc705c0f3fc428981ff5689c04b519fadf83cbc9fcd0409c326035045df480570e265bb080940037ce4076a36437aafdb371c1a62af9ad9b614dfef89708fbbb5ebef2cb9528cc399781e4c5b22f1aa4dba623809f", MD: "5f76962fd3d373e5db2953c0823a51fe81f874450bedf7e46876394b04d3ef66"); + yield return (Msg: "e03115cfa19efcd796da389063c4be6acce684d983f8edfb3da6887b0b94fbb5e89e3a1a8e64fdd68f0670b1a02c2c33384a660c5a2266b3ae8a3b4cd76faecf011a7467b9b2a818020278a5a57d1eb1c87f1224c2d67dd02e81f1553eb75841532c2b7cca8fe5e418", MD: "d107ee6ee4a58871a33c49657faa2573e475f11918c4a4e3801d0e17fb93c6e3"); + yield return (Msg: "0e6c1d58b1b9d3a2d399aafd60529e07d483a2755bb7e44c373b5355632d5fca76d6ff56c93af93ddcec5ed6f62753420c1b1758e48542df7b824b00a3a54dfaf0470b18d51e31e10b12dd8e324b5dc1bb8f3b7305cb762ec6ef137dadffd4a2466748861d9004f626b0", MD: "02ab2dbb02944354799051247b1a25c19f3696e1afcb502b859e83798b33fd77"); + yield return (Msg: "6db2a43a229b10c3629249fc5136468b4d84df7b89ec90ebf7aa7a036c53aa2dffae9e81b2c60580543dc706a5e3457abc87e248a60ec29150c2d221a6ec08a1fda4ec0daee8576904ec7ab059b1230e7bd93c4e55ba9496cbb1e352e5b8086e303b94c861288ce53c466b", MD: "8cc4d39b2f5ba0bc9d2ee2a8777cf08533e60cc69b65a7b31c5c2121193aa31e"); + yield return (Msg: "31d995f7ff8b6de70829a8336c610f10df2c866107a4922b25151849f8566861df5a79163d02767f21357ad82733997899261f03dafb1ce1056f20efd16d4374b89768565823c38e19e899d910b847b023f1867b6e4fed02e604b8243c0bc7cb05b9ea1f17955bfa36698c9c", MD: "c99c7191b34c9ad3f941d4ad442cc865205cbb4c2a6927c592e831cbc4d36fcf"); + yield return (Msg: "cb0b8cb7de621c8e0a0fc6be2fc18d0e8818a2c2dd0b3219fa87831a61583f903c4d105495976ccac973b3ae3a09771145931a9e74c19f22f45cba4c492b29b1401347122581dfe2370d3e0359578cd10a355c619711810a8f8c232578671312c0a45c7cf7e81bdd3b249044f3", MD: "6d2f57a7e42b35369cf2cd60caf9e65aca7d9aa019e6824bb806348f1acf3c7c"); + yield return (Msg: "48dff78aed5f6e823054924a78dc1b8e51a117f1610181529f6d164ebf0f6406f0b02422cad8c916823759a361437ca17423d3fd84cc8afe486a31ccda01c732685418a32c064a7b9effb288e811ecc99adb2a759feecc3f702f31d9877dcdb717937c15fa2f163bea744400f58c", MD: "14b631f0f00a3024ad1810dabf02711e28449668abe27f69380942268968d4f6"); + yield return (Msg: "06cc9fa542ceb35c88fb6ab82c29d5dcd530f807d3f1c3bcb3974421101d1aa6ac112de6bf979cd28eb0f70c40bcaf91ed3eca9bf9e0dbc6a0b73271d1c7506740ca9ebfb72d5e00ac5ce189193ffa308804b42a6d20402bb99031cdac65ec36eb7f59f5d299df2e0b8690f760b9a0", MD: "574fd82a9fceb8f7bbbf244d16e0412cbda8153b720846c32b8f10fe5779a881"); + yield return (Msg: "8d93627c0b7cbf61a7fe70e78c2c8ed23b1344b4cfed31bd85980dd37b4690e5b8758f7d6d2269957a39a1ac3451cc196696ae9e9606a04089e13456095a1ce1e593481b3ac84f53f1cb10f789b099f316c948398ad52fa13474bdf486de9b431bd5d57ef9d83a42139a05f112b2bd08", MD: "344ec86642eabb206b2fd930e4c5dde78aa878577d6c271cb0069d4999495652"); + yield return (Msg: "d0af484b8be6b41c1971ae9d90650a1e894356c9191d6be303fa424f2b7c09544ec076a0f1865c8c97927ca137529d5bedc0df2ef08a4cc7c470b094b1eeaa86731c041633d24086b60f7369d59c57652dec9b3817477df9db289ba020e306c9a78a99b539128992deb23cfc508c5fc3af", MD: "b7ba998726477c32792e9c3eddc1cb6feb7c3933e49f2e7590d8ce7a2113e6f8"); + yield return (Msg: "b212f7ef04ffcdcf72c39a6309486c0eeb390ff8f218d6bd978b976612f7f898c350e90bd130723e1126af69295019b4f52c06a629ab74e03887020b75d73f0f78e12785c42feb70a7e5f12761511c9688c44da6aaa02afa35b31edc94c3a0779b6ab9462525c0ccfba76986f873fe1e6ba9", MD: "2f26b96c1fa3f3dee728f17584e733b4189821c659b8885a5fb1d12d60d2aaa9"); + yield return (Msg: "86591ada83fba8175a0fe91d264e7f9b2df97ee4c32570e76b579d6140508951932abdadd6a4ca53b8bb8c42927aac0a02126881d52d97b82b80e72dd59f6a42021651ee1bb5f7b3eb2b21d003d784b75dda87c13f714b216282e8175474fa661b445d071bd5341f3a88302f410d0f8a857962", MD: "e3edbc8c42ce5d2384dfb24fb1de5d4798b1bc3cc78c97033894040dfa6feb6c"); + yield return (Msg: "92b5a8e84b6a2ac4d5b1e61d63804abd641dd630058ec6d5f752f135724ef1947a0a84c6611d32448de6307f7b7d857404e96b81df94f87768fcfdf09faa2fe37468847542afe012995ff1bd40b257a47a7309f8896bf4fb711de55bfeb3a8be0837729ef6067c578182f17ebb080a754f22773c", MD: "80ed0a702812297c2aa1b6b4b530c2b5ed17ecfba6d51791cf152d4303ced2e6"); + yield return (Msg: "d284a0a9a4de5d4c68cc23884c95ad7619aa39b20a2cf401deaeb3362c3ce356f79cc3fa82d3d1f565ec8137e1f435f171496afaa1152f722315dca5209f0031cce39b6c3d718e007dfb4fd8de5ce1408dda04476aa8a96817afa86a4f8fb5857ae091c67ebd7db5d783f434ead699aa96e56f610d", MD: "654eccefd0a4fdb2ac0ab56288c64399b37bc4d57ff4a9f1cce94362fc491bda"); + yield return (Msg: "f57f0f8795385b805246a0a2573afc274346a9eccf50c626b0455a50bfb09668578b5a5afe54fbbd486444bdf97dba586aa224ce2e2b4b52f418ff06afa65a26f5204983a5f84734cd166c88cb70a73fb2db48f9ef20c1ee2c53ade07460114e98e7e2ebd24ac84ea90422eb143c4a42e2991a565959", MD: "135ec8b144a667dceae8fadd287df81c10ef3ebef87ff2fb56e60ae708a88f3b"); + yield return (Msg: "2a41a52e6578873588a57f11f1be7c7eb398d01f3bfdec2c33fe6b65a68a534a6540978daa82e0c8fccb8c6c5242f7f97b8ffa75bdedb217bd8083439eea5cbb6d193c13bd62f5658ed4304774c6b1faf5b3dce432487840cabab415fb5d67640a739ca6e5414e760869708a9d7331e7e7ad7d55e035c7", MD: "a6a1b8a26f6f440f19f16dce1d3001477d73ee7f6c374bce2922167b81970d6a"); + yield return (Msg: "4d11aa5d3c6b6900f49ff90dd815744572be5648b64bde638b9db7a9877dd745fa8ea80e2f7f655cee85c71a4509e21d899e49b4973579815f947587a404ad83fd4a248020d9d2a65f46485373fc926d793161f63a196ae0af590923c5be2a0e5d2f69da97e0788550c9c1dee9574ddc4a61e533275d7729", MD: "fc5159f0ddd6d765c85fcc3fc3ac1dc0d317d8ea0b110e96ac9f7a398dc386c5"); + yield return (Msg: "05cd99bfe031d123ca7061d3de0956f4bbf164bad792db881713d6599ddab55ee24fcee804e360896152c8766424f8309f7a24641a07be0feb5da5e5076a9af45842f385101f93433ca5199f9c6b5872b2b808e4198aba8e18dd12db772930b4912d6f5cabeb529884f4bb142de55e021b3276047b22b64cc5", MD: "8aa07742e6f1f47ad020ed6684edc8dba4af36b782955f0f972be3ae980aea0e"); + yield return (Msg: "529684398d68bdc19e7a00ce32cc1a8c1315b97f07137474f61f0cb84a04f2879b1109c78c6dacf7f0abf362329e3298f36fc31ef4ec06653723a5f961301dfb63537ad15946611cb2cd54ea928e322e7423fd6d146ee0b98c2c71e3bdcd33edf0845fbebd9ae4192d07acd01b432135e05af0d22f3f0c5a3d62", MD: "a07049b6ebd7b355479a3d802fda436b83ae6747d741cf9626f7c62f47cbd563"); + yield return (Msg: "982fb5f4af498a4a75e33a033235ea3ddb70d9d236519f883ff5b388cbef30126b98d96e93a65a26fb00d17246d18cf4e2db14a52f0f6b10e35a93beadc14ff118b02e95b38fc4736f973ba848e40b5527cb0599076d96bc578c4aada09e8faf6820bc4f562d5199974f808b7f95edca74e6b3940894a7f66534e0", MD: "09c60fec5a089a23f5da3ed2492aa21fcf7aa36183850fafc15ae8c63f596db0"); + yield return (Msg: "ca88614828f8acdb5fcffab6bb2fb62d932b7808e4d9cc3139a835b0cef471d9f4d8ffc4b744dffebf4f997e74ce80db662538bceb5d768f0a77077e9700149ea0e6a46a088a62717216a14b60119dd19c31038ed870b4709161c6c339c5cc60945a582263f3be9a40cd1a04c921947900f6e266f2390f3c970f7b69", MD: "fe2d4183ccdaa816b4446a9b6c07d0ba4b42ac743599db5dc482b1941f443c71"); + yield return (Msg: "ab6b92daf83275cb9c1b76cfb59fbcc8ac53188e0b6980918e7ac0c07c836ca9372d19e11251cca664bbb3c3db2e13b412a9820b65e95612042f5db24643cf9340b9808597735a1f92670ba573a2fb2f088d81087d70565574344af7576d35b2ed98318e2ca0067d4fa8e63f28045b83b6887d4ffa0668a10712ed5759", MD: "744538e1ae1cd7357710b56c3bc6f1bd7a8564118a1e0f9acc30fcf0b5396eef"); + yield return (Msg: "bfd4c7c8e90858ccf9c8834abefd9c1846ca4a11966fdd139d6de24a6bebf4b19f58d5d51e52bddd0bc6f1c7f35998f44707cae7100aeb4adefe373101429da3fca1d15737329dbbf47c783a84de59bfbb2fcd75a1a148d26aebb8d3a9a76089c0f8e4d49b71a06f9e323e2cdb54888189887a44b1fa9cb32b7c8fb7c9e0", MD: "58b17843bc851a721c5a258eef57b3854d02190e732d9b8e7a9f926ac409c173"); + yield return (Msg: "c5019433c285da2bb93f119e58b4f36cd1e4d99dda35dbf4f8ae39c7fe65fa0ed03bd2b96dc649472d8f1a94477ed9f29592d97c9cd54da7c790ad1af3bb5cc030b7871bc64050db779d2caf0419895bf3b7b50b8e22fbe62fe30fe7bbd6ace86ddf7b00d5d9370f20cf0f97996f4bce70bb33f1ba022cdaba0f25d55fa031", MD: "f7c92a3fb7f180370d628be78de874d693f74ccc7a54c741634258d8c512fd7f"); + yield return (Msg: "84b60cb3720bf29748483cf7abd0d1f1d9380459dfa968460c86e5d1a54f0b19dac6a78bf9509460e29dd466bb8bdf04e5483b782eb74d6448166f897add43d295e946942ad9a814fab95b4aaede6ae4c8108c8edaeff971f58f7cf96566c9dc9b6812586b70d5bc78e2f829ec8e179a6cd81d224b161175fd3a33aacfb1483f", MD: "8814630a39dcb99792cc4e08cae5dd078973d15cd19f17bacf04deda9e62c45f"); + yield return (Msg: "14365d3301150d7c5ba6bb8c1fc26e9dab218fc5d01c9ed528b72482aadee9c27bef667907797d55514468f68791f053daa2df598d7db7d54beea493bdcbb0c75c7b36ad84b9996dca96354190bd96d9d7fbe8ff54ffaf77c55eb92985da50825ee3b4179f5ec88b6fa60bb361d0caf9493494fe4d28ef843f0f498a2a9331b82a", MD: "9b690531dee948a9c559a2e0efab2ec824151a9175f2730a030b748d07cbaa7f"); + yield return (Msg: "4a757db93f6d4c6529211d70d5f8491799c0f73ae7f24bbd2138db2eaf2c63a85063b9f7adaa03fc348f275323248334e3ffdf9798859f9cf6693d29566ff7d50976c505ecb58e543c459b39acdf4ce4b5e80a682eaa7c1f1ce5fe4acb864ff91eb6892b23165735ea49626898b40ceeb78161f5d0ea4a103cb404d937f9d1dc362b", MD: "1ac7cc7e2e8ea14fb1b90096f41265100712c5dd41519d78b2786cfb6355af72"); + yield return (Msg: "da11c39c77250f6264dda4b096341ff9c4cc2c900633b20ea1664bf32193f790a923112488f882450cf334819bbaca46ffb88eff0265aa803bc79ca42739e4347c6bff0bb9aa99780261ffe42be0d3b5135d03723338fb2776841a0b4bc26360f9ef769b34c2bec5ed2feb216e2fa30fa5c37430c0360ecbfba3af6fb6b8dedacbb95c", MD: "c163cd43de224ac5c262ae39db746cfcad66074ebaec4a6da23d86b310520f21"); + yield return (Msg: "3341ca020d4835838b0d6c8f93aaaebb7af60730d208c85283f6369f1ee27fd96d38f2674f316ef9c29c1b6b42dd59ec5236f65f5845a401adceaa4cf5bbd91cac61c21102052634e99faedd6cdddcd4426b42b6a372f29a5a5f35f51ce580bb1845a3c7cfcd447d269e8caeb9b320bb731f53fe5c969a65b12f40603a685afed86bfe53", MD: "6c3e93f2b49f493344cc3eb1e9454f79363032beee2f7ea65b3d994b5cae438f"); + yield return (Msg: "989fc49594afc73405bacee4dbbe7135804f800368de39e2ea3bbec04e59c6c52752927ee3aa233ba0d8aab5410240f4c109d770c8c570777c928fce9a0bec9bc5156c821e204f0f14a9ab547e0319d3e758ae9e28eb2dbc3d9f7acf51bd52f41bf23aeb6d97b5780a35ba08b94965989744edd3b1d6d67ad26c68099af85f98d0f0e4fff9", MD: "b10adeb6a9395a48788931d45a7b4e4f69300a76d8b716c40c614c3113a0f051"); + yield return (Msg: "e5022f4c7dfe2dbd207105e2f27aaedd5a765c27c0bc60de958b49609440501848ccf398cf66dfe8dd7d131e04f1432f32827a057b8904d218e68ba3b0398038d755bd13d5f168cfa8a11ab34c0540873940c2a62eace3552dcd6953c683fdb29983d4e417078f1988c560c9521e6f8c78997c32618fc510db282a985f868f2d973f82351d11", MD: "3293a4b9aeb8a65e1014d3847500ffc8241594e9c4564cbd7ce978bfa50767fe"); + yield return (Msg: "b1f6076509938432145bb15dbe1a7b2e007934be5f753908b50fd24333455970a7429f2ffbd28bd6fe1804c4688311f318fe3fcd9f6744410243e115bcb00d7e039a4fee4c326c2d119c42abd2e8f4155a44472643704cc0bc72403b8a8ab0fd4d68e04a059d6e5ed45033b906326abb4eb4147052779bad6a03b55ca5bd8b140e131bed2dfada", MD: "f82d9602b231d332d902cb6436b15aef89acc591cb8626233ced20c0a6e80d7a"); + yield return (Msg: "56ea14d7fcb0db748ff649aaa5d0afdc2357528a9aad6076d73b2805b53d89e73681abfad26bee6c0f3d20215295f354f538ae80990d2281be6de0f6919aa9eb048c26b524f4d91ca87b54c0c54aa9b54ad02171e8bf31e8d158a9f586e92ffce994ecce9a5185cc80364d50a6f7b94849a914242fcb73f33a86ecc83c3403630d20650ddb8cd9c4", MD: "4beae3515ba35ec8cbd1d94567e22b0d7809c466abfbafe9610349597ba15b45"); + + // First 5 from SHA3_256LongMsg.rsp + yield return ( + Msg: + "b1caa396771a09a1db9bc20543e988e359d47c2a616417bbca1b62cb02796a888fc6eeff5c0b5c3d5062fcb4256f6ae1782f492c1cf03610b4a1fb7b814c057878e1190b9835425c7a4a0e182ad1f91535ed2a35033a5d8c670e21c575ff43c194a58a82d4a1a44881dd61f9f8161fc6b998860cbe4975780be93b6f87980bad0a99aa2cb7556b47" + + "8ca35d1f3746c33e2bb7c47af426641cc7bbb3425e2144820345e1d0ea5b7da2c3236a52906acdc3b4d34e474dd714c0c40bf006a3a1d889a632983814bbc4a14fe5f159aa89249e7c738b3b73666bac2a615a83fd21ae0a1ce7352ade7b278b587158fd2fabb217aa1fe31d0bda53272045598015a8ae4d8cec226fefa58daa05500906c4d85e75" + + "67", + MD: "cb5648a1d61c6c5bdacd96f81c9591debc3950dcf658145b8d996570ba881a05"); + + yield return ( + Msg: + "712b03d9ebe78d3a032a612939c518a6166ca9a161183a7596aa35b294d19d1f962da3ff64b57494cb5656e24adcf3b50e16f4e52135d2d9de76e94aa801cf49db10e384035329c54c9455bb3a9725fd9a44f44cb9078d18d3783d46ce372c31281aecef2f8b53d5702b863d71bc5786a33dd15d9256103b5ff7572f703d5cde6695e6c84f239acd" + + "1d6512ef581330590f4ab2a114ea064a693d5f8df5d908587bc7f998cde4a8b43d8821595566597dc8b3bf9ea78b154bd8907ee6c5d4d8a851f94be510962292b7ddda04d17b79fab4c022deb400e5489639dbc448f573d5cf72073a8001b36f73ac6677351b39d9bdb900e9a1121f488a7fa0aee60682e7dc7c531c85ec0154593ded3ae70e4121" + + "cae58445d8896b549cacf22d07cdace7625d57158721b44851d796d6511c38dac28dd37cbf2d7073b407fbc813149adc485e3dacee66755443c389d2d90dc70d8ff91816c0c5d7adbad7e30772a1f3ce76c72a6a2284ec7f174aefb6e9a895c118717999421b470a9665d2728c3c60c6d3e048d58b43c0d1b5b2f00be8b64bfe453d1e8fadf56993" + + "31f9", + MD: "095dcd0bc55206d2e1e715fb7173fc16a81979f278495dfc69a6d8f3174eba5a"); + + yield return ( + Msg: + "2a459282195123ebc6cf5782ab611a11b9487706f7795e236df3a476404f4b8c1e9904e2dc5ef29c5e06b179b8649707928c3913d1e53164747f1fa9bba6eeaf8fb759d71e32adc8c611d061345882f1cdeee3ab4cab3554adb2e43f4b01c37b4546994b25f4dcd6c497bc206865643930157cb5b2f4f25be235fa223688535907efcc253bcd0830" + + "21407ea09cb1c34684aa0c1849e7efe2d9af6938c46525af9e5afb4da6e5b83da4b61dc718672a8090549cbe5aadb44f5bc93a6b3fbdc2e6d32e2eaaae637465179ea17f23ad1e4f1ebc328e2c6dc90c302b74a1edbbb0676c136b269d70c41040a313af06ab291bf489d9700950b77f207c1fc41884799931b3bca8b93331a6e96b7a3f0a8bd24c" + + "db64964c377e0512f36444bb0643a4e3ecb328194cd5428fd89ede167472a14a9bf5730aff1e3b2c708de96eff1ebaaf63beb75f9c7d8034d6e5471e8f8a1f7efce37793a958e134619c19c54d3d42645f7a7263f25471fbaae8be3ea2fbd34ec6d7aacd7d5680948c3cd9a837c9c469a88f600d95829f4d1e4e4a5ef4ed4623c07815a1c33d9fb3" + + "b91333ff04eac92806a68a46cf2e9293f8bff466ce87fe66b46fbff7c238c7f9b2c92eb2fdc7d8084167f6f4e680d03301e5c33f78f1857d6863b1b8c36c7fce3e07d2a96a8979712079ae0023a1e3970165bfcf3a5463d2a4fdf1ca0e044f9a247528cd935734cb6d85ba53ceb95325c0eaf0ff5cd81ecb32e58917eb26bfc52dba3704bf5a927f" + + "ee3220", + MD: "cb1c691c87244c0caf733aacd427f83412cd48820b358c1b15dd9fadee54e5af"); + + yield return ( + Msg: + "32659902674c94473a283be00835eb86339d394a189a87da41dad500db27da6b6a4753b2bb219c961a227d88c6df466ba2fc1e9a2d4c982db4398778c76714d5e9940da48bc3808f3c9989131a07683b8c29d6af336e9aee1dfa57d83c48a86f17146edec07869bb06550689ebf4788159ed0a921048b4a6e3e3ec272413bec15d8e1f6a40897fa0" + + "e11d9df223ef9fc270106249ae220fdc6ebdef6d6611805421ccc850f53ee9c836baf657a94005883b5a85def344d218264f07b2ea8714afcc941096c6ded0bb6bf5b8bf652fd15a21931c58c9f526e27363ddff98c0a25bc7af9f469ab35bffea948b333f042cc18a82cec0177f33c3bdbf185b580353de79e51e675b03b31e195f19ba1f063d44" + + "def0441dc52820426c2c61cf12974ec249fd3502f017ffa06220075ced7e2d6b86a52677ba3916e8e8726062aec5bc8ea1c18b1e4137680b2c9d002191b423bee8691bd7e0f93c3b9959bc1c14d5c5cbe8f7c9c336aa16e9de9faa12f3f048c66d04cb441eb2bbc5e8a91e052c0f9000856896f9b7ba30c1e2eead36fc7ac30a7d3ddfc65caaba0e" + + "3b292d26dfba46b5e2dc9bc9acadde1c9f52b2969299bd1281ddff65822b629cfba2928613200e73661b803afdcc4a817d9361389e975e67dfadd22a797bdaf991ddf42db18711c079ecec55925f9978e478612609bacd900172011c27e24bad639ffc24a23877278318872153aef6893ccb5b68b94b33154df7334375aadd3edbb35272cc7b672d" + + "ec68faa62900873ded52f6049891b77f2d0311a84b19b73660e09d1f1998095c1da1edecfa9f741b5fd6db048dd68255085d43529279021d59ed853470d6863b7c8e07fcb0d1e6acfb1eb16f7f60bb1f46ce70493010e57930a3b4b8b87e065272f6f1dd31df057627f4214e58798b664e1e40960f2789d44ccacfb3dbd8b02a68a053976711f803" + + "4c1ed3a8", + MD: "5ac9275e02543410359a3f364b2ae3b85763321fd6d374d13fe54314e5561b01"); + + yield return ( + Msg: + "a65da8277a3b3738432bca9822d43b3d810cdad3b0ed2468d02bd269f1a416cd77392190c2dde8630eeb28a297bda786017abe9cf82f14751422ac9fff6322d5d9a33173db49792d3bc37fff501af667f7ca3dd335d028551e04039ef5a9d42a9443e1b80ea872fd945ad8999514ae4a29a35f60b0f7e971b67ae04d1ba1b53470c03847a3225c3d" + + "df593a57aed3599661ae2d2bb1cddd2fa62c4a94b8704c5c35c33e08e2debe54e567ae21e27e7eb36593ae1c807a8ef8b5c1495b15412108aaf3fce4130520aa6e2d3bdf7b3ea609fdf9ea1c64258435aae2e58a7b3abda198f979c17dbe0aa74253e979bf3a5800f388ea11a7f7454c4e36270a3083a790c77cbe89693205b32880c0d8f79b1c00" + + "0ee9b5e58f175ba7696616c17c45673cff25d1221f899836e95cc9e26a887a7115c4537e65ad4eacc319ba98a9a8860c089cbc76e7ea4c984d900b80622afbbbd1c0cdc670e3a4c523f81c77fed38b6aa988876b097da8411cc48e9b25a826460a862aa3fadfe75952aa4347c2effebdac9138ebcc6c34991e9f5b19fc2b847a87be72ff49c99ecf" + + "19d837ee3e23686cd760d9dd7adc78091bca79e42fdb9bc0120faec1a6ca52913e2a0156ba9850e1f39d712859f7fdf7daedf0e206dff67e7121e5d1590a8a068947a8657d753e83c7f009b6b2e54acc24afc9fdc9601a1d6d9d1f17aab0ce96c4d83405d1e3baba1dffa86ecccee7f1c1b80b1bbf859106ce2b647ae1e4a6a9b584ae1dfc0a4dee" + + "bb755638f1d95dcc79b1be263177e2a05c72bde545d09ba726f41d9547117e876af81bfc672e33c71442eb05675d9552df1b313d1f9934f9ddd08955fa21d6edf23000a277f6f149591299a0a96032861ecdc96bb76afa05a2bffb445d61dc891bc70c13695920b911cad0df3fa842a3e2318c57556974343f69794cb8fa18c1ad624835857e4781" + + "041198aa705c4d11f3ef82e941be2aee7a770e54521312fe6facbaf1138eee08fa90fae986a5d93719aeb30ac292a49c1d91bf4574d553a92a4a6c305ab09db6bbeffd84c7aa707f1c1628a0220d6ba4ee5e960566686228a6e766d8a30dddf30ed5aa637c949950c3d0e894a7560670b6879a7d70f3c7e5ab29aed236cc3527bdea076fec8add12" + + "d784fbcf9a", + MD: "68f62c418a6b97026cc70f6abf8419b671ee373709fa13074e37bd39f0a50fcb"); + } + } + } +} diff --git a/src/libraries/System.Security.Cryptography/tests/Sha3_384Tests.cs b/src/libraries/System.Security.Cryptography/tests/Sha3_384Tests.cs new file mode 100644 index 00000000000000..468c38823fbc11 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/tests/Sha3_384Tests.cs @@ -0,0 +1,291 @@ +// 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.IO; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace System.Security.Cryptography.Tests +{ + public class SHA3_384Tests : HashAlgorithmTestDriver + { + public sealed class Traits : IHashTrait + { + public static bool IsSupported => SHA3_384.IsSupported; + public static int HashSizeInBytes => SHA3_384.HashSizeInBytes; + } + + protected override HashAlgorithm Create() + { + return SHA3_384.Create(); + } + + protected override bool TryHashData(ReadOnlySpan source, Span destination, out int bytesWritten) + { + return SHA3_384.TryHashData(source, destination, out bytesWritten); + } + + protected override byte[] HashData(byte[] source) => SHA3_384.HashData(source); + + protected override byte[] HashData(ReadOnlySpan source) => SHA3_384.HashData(source); + + protected override int HashData(ReadOnlySpan source, Span destination) => + SHA3_384.HashData(source, destination); + + protected override int HashData(Stream source, Span destination) => + SHA3_384.HashData(source, destination); + + protected override byte[] HashData(Stream source) => SHA3_384.HashData(source); + + protected override ValueTask HashDataAsync(Stream source, Memory destination, CancellationToken cancellationToken) => + SHA3_384.HashDataAsync(source, destination, cancellationToken); + + protected override ValueTask HashDataAsync(Stream source, CancellationToken cancellationToken) => + SHA3_384.HashDataAsync(source, cancellationToken); + + [ConditionalFact(nameof(IsSupported))] + public void SHA3_384_Kats() + { + foreach ((string Msg, string MD) kat in Fips202Kats) + { + Verify(Convert.FromHexString(kat.Msg), kat.MD); + } + } + + [ConditionalFact(nameof(IsSupported))] + public void SHA3_384_Empty_Stream() + { + VerifyRepeating( + "", + 0, + "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004"); + } + + [ConditionalFact(nameof(IsSupported))] + public async Task SHA3_384_Empty_Stream_Async() + { + await VerifyRepeatingAsync( + "", + 0, + "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004"); + } + + [ConditionalFact(nameof(IsSupported))] + public void SHA3_384_VerifyLargeStream_MultipleOf4096() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl dgst -sha3-384 + VerifyRepeating( + "0102030405060708", + 1024, + "0aa96c328926f2faa796dc75a104e200f5b497beb0313e8822b471efebbb39cef02687e33787883a87c18f35856dcad1"); + } + + [ConditionalFact(nameof(IsSupported))] + public void SHA3_384_VerifyLargeStream_NotMultipleOf4096() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl dgst -sha3-384 + VerifyRepeating( + "0102030405060708", + 1025, + "e2d1714c8011e7b90550123006128d90fa464cb71903e4aa67342bc8780eb43ae099a2d8610e0ba3061f4f3792d344a7"); + } + + [ConditionalFact(nameof(IsSupported))] + public async Task SHA3_384_VerifyLargeStream_NotMultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl dgst -sha3-384 + await VerifyRepeatingAsync( + "0102030405060708", + 1025, + "e2d1714c8011e7b90550123006128d90fa464cb71903e4aa67342bc8780eb43ae099a2d8610e0ba3061f4f3792d344a7"); + } + + [ConditionalFact(nameof(IsSupported))] + public async Task SHA3_384_VerifyLargeStream_MultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl dgst -sha3-384 + await VerifyRepeatingAsync( + "0102030405060708", + 1024, + "0aa96c328926f2faa796dc75a104e200f5b497beb0313e8822b471efebbb39cef02687e33787883a87c18f35856dcad1"); + } + + [Fact] + public void SHA3_384_HashSizes() + { + Assert.Equal(384, SHA3_384.HashSizeInBits); + Assert.Equal(48, SHA3_384.HashSizeInBytes); + } + + [Fact] + public void SHA3_384_IsSupported_AgreesWithPlatformVersion() + { + Assert.Equal(PlatformDetection.SupportsSha3, SHA3_384.IsSupported); + } + + private static IEnumerable<(string Msg, string MD)> Fips202Kats + { + get + { + // Generated from SHA3_384ShortMsg.rsp + yield return (Msg: "", MD: "0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004"); + yield return (Msg: "80", MD: "7541384852e10ff10d5fb6a7213a4a6c15ccc86d8bc1068ac04f69277142944f4ee50d91fdc56553db06b2f5039c8ab7"); + yield return (Msg: "fb52", MD: "d73a9d0e7f1802352ea54f3e062d3910577bf87edda48101de92a3de957e698b836085f5f10cab1de19fd0c906e48385"); + yield return (Msg: "6ab7d6", MD: "ea12d6d32d69ad2154a57e0e1be481a45add739ee7dd6e2a27e544b6c8b5ad122654bbf95134d567987156295d5e57db"); + yield return (Msg: "11587dcb", MD: "cb6e6ce4a266d438ddd52867f2e183021be50223c7d57f8fdcaa18093a9d0126607df026c025bff40bc314af43fd8a08"); + yield return (Msg: "4d7fc6cae6", MD: "e570d463a010c71b78acd7f9790c78ce946e00cc54dae82bfc3833a10f0d8d35b03cbb4aa2f9ba4b27498807a397cd47"); + yield return (Msg: "5a6659e9f0e7", MD: "21b1f3f63b907f968821185a7fe30b16d47e1d6ee5b9c80be68947854de7a8ef4a03a6b2e4ec96abdd4fa29ab9796f28"); + yield return (Msg: "17510eca2fe11b", MD: "35fba6958b6c68eae8f2b5f5bdf5ebcc565252bc70f983548c2dfd5406f111a0a95b1bb9a639988c8d65da912d2c3ea2"); + yield return (Msg: "c44a2c58c84c393a", MD: "60ad40f964d0edcf19281e415f7389968275ff613199a069c916a0ff7ef65503b740683162a622b913d43a46559e913c"); + yield return (Msg: "a36e5a59043b6333d7", MD: "bd045661663436d07720ff3c8b6f922066dfe244456a56ca46dfb3f7e271116d932107c7b04cc7c60173e08d0c2e107c"); + yield return (Msg: "c0920f2bd1e2d302259b", MD: "3d1584220409f88d38409a29ecaebb490ef884b5acba2c7eaf23914bab7f5f0fc97ee1e6336f88dfd4d0a06e902ccd25"); + yield return (Msg: "70ae731af5e0d92d264ec9", MD: "563359fd93fe09f3fe49fcf5f17e7f92aab589cdec3e55e4c3715e7775814bbbfb8c4c732e28d3b6e6404860812dc6e9"); + yield return (Msg: "69c74a9b0db538eeff64d93d", MD: "88c66389ca2c320a39022aa441fa884fbc6ed2d3cc9ac475372d947d4960579a64e061a297d1831d3524f98d8094404b"); + yield return (Msg: "a4a9327be21b9277e08c40abc7", MD: "751f5da5ff9e2460c99348070d5068d8a3d7ffcec7fd0e6f68f6cd4a2ef4226df8d9b4613c3b0d10a168eaf54eabe01a"); + yield return (Msg: "cc4764d3e295097298f2af8882f6", MD: "10f287f256643ad0dfb5955dd34587882e445cd5ae8da337e7c170fc0c1e48a03fb7a54ec71335113dbdccccc944da41"); + yield return (Msg: "5a23ad0ce89e0fb1df4a95bb2488f0", MD: "23840671e7570a248cf3579c7c8810b5fcc35b975a3a43b506cc67faefa6dbe1c945abc09a903e199f759dcbc7f2c4d0"); + yield return (Msg: "65b27f6c5578a4d5d9f6519c554c3097", MD: "dd734f4987fe1a71455cf9fb1ee8986882c82448827a7880fc90d2043c33b5cbc0ed58b8529e4c6bc3a7288829e0a40d"); + yield return (Msg: "a74847930a03abeea473e1f3dc30b88815", MD: "dba6f929fe55f9d66c5f67c0af3b82f17bcf58b36752f3165c16083fea8fd478ee6903f27f820ad2dd9950afb48c6700"); + yield return (Msg: "6efaf78ed4d293927eef2c3a71930e6e887a", MD: "8218498ab01b63041c2ba0709e3309496124ddf0904543a9e0d9d096a750dda97f7a02208af3d8c618d4be7c2bb2a288"); + yield return (Msg: "fd039eb6e4657388b947ec01e737efbbad47da", MD: "c5b3130ef8dbc580e1103fecae69c9a882d9ebf5a3def5938b07f843452a09c9f72f0dbca91d33b021cf6aa6fe60d2ed"); + yield return (Msg: "9c694943389bdc4e05ad7c2f63ceac2820e1d2d7", MD: "f692c025c5c5f3d1275213c1df9bf9eb6d2188eda90ab5bffe631f1dbf70ebd628caee88b7d149e1ac4e262873979afe"); + yield return (Msg: "0fb18357b018b9bbb2cbb4cac50bc85609c92b8e7f", MD: "d164306c99e3798790f0923fe92dbf2f96c3907127dacaa467c766ac75788062589272cb7690b8af2030dd8bd61a3df2"); + yield return (Msg: "26cb40a460e2e727aeb867e0140d0f34790110deb5d7", MD: "af2a42a4c67c3226c55b89605b0dee27e796c2792115f6097203db5aed89e35f563a8246d399fde00c2a5b97ed5a5e17"); + yield return (Msg: "6690a3a0373c829facc56f824382f4feed6eb184642b4f", MD: "84e1b68bc9e2daefc19b567dec911ef46f5f37a74fdbbb6155e7e646f2735df2ac44e239689eb5b536465dc571e55cb2"); + yield return (Msg: "7d80b160c4b536a3beb79980599344047c5f82a1dfc3eed4", MD: "041cc5861ba334563c61d4ef9710d4896c311c92edbe0d7cd53e803bf2f4eb6057235570770ce87c5520d7ec14198722"); + yield return (Msg: "02128283ffc0cfe254ac8f542be3f05fbe4e855dd22ae98a81", MD: "3840981a766d725f83d334e8982965033a5fbb5107d94ffef33b1f700cd46348091a49f6620c37ae3ef5b20513494826"); + yield return (Msg: "27911dd0a6843ccae965d876aa1916f1dcd71e518f7f2197152e", MD: "f59f8428555984d1526cded8129c649fb1b683d35cec7c5e1209441a6a9e7c17f0784151b5ab8a8c492b402a3acb98c4"); + yield return (Msg: "d9378bb66e8c8dee556d691cbc9fdddd6333ca5d50668862c3c57d", MD: "994532d1a557e990b1cc9e0395a2ad8b05619ca322db9da3c4ed2ee194c051d04582fde72dd2b8f674cf6ec958db75da"); + yield return (Msg: "ae1828047c5f82a7b9712f3399832124b892f2f7aea51c8fe3536cd6", MD: "d51111f8bffb44d81ad19683198f29d2033144d3cd856c749cac5b9cae0e712f500f8d0ef813f38e305ce175a7d6162c"); + yield return (Msg: "7dd2d76fa054cf461e132e9ef914acdc53080a508cdc5368ab8c6224ff", MD: "6c0b3395e4c86518ab0a06267320ee9ec95e50385b7a2527ddaa1bd0ead262c56122d4f4eb08b0ae22b3ee7e6f44dd18"); + yield return (Msg: "6fd72888a021f36e550967cb5605b55b78657c9272d93c3ded340d67da6f", MD: "0551583a5b4007401c77ef4382fd8e245c9cf12e976c9766af6b7ae3c7e07a82b3079f903b083d5ec85cb94e46a85ac0"); + yield return (Msg: "d500eb9546553619cdc31e0848c502db92d547efef3ae5eeaa22258afcf0a9", MD: "5edde2f94f8695f277ec05efcc00761fafd272200aed0e63d221c2b6c65b4972a6526f9a1f2e6ace0e81938f043fe877"); + yield return (Msg: "6189597e0198a18c65fa0bdd0797f13037c75c4058b7d3454c0f71bd2dd13b6c", MD: "110630ca7631b7620e6bee6ed6e929098965571936c34829484983eba9532b8175528c228c57439453f027a4f7c83ca3"); + yield return (Msg: "243b941d748541af303f8e9d2c371cd03e437d62a9df485ddc176dc65da8c7da00", MD: "5884201f7a555ea3c5deeb019fd9e8c161e1b89756045e475b141ec5135ce5a41c93e5e1f79534d36fd8345ba434da43"); + yield return (Msg: "2dc3d789582c1a806c3b491d5972ef8f1733f1f5e02866dc9de2a8029ec0ab608d13", MD: "05a3903b519cdf679120c7ccb4ef178b58e4502fcd461360988fa06669294851e629d9dd3e77ffb73d24599d5d3edd36"); + yield return (Msg: "e5b3f6962fe57230780b3d55b29effe0dfebde2c81ba97d4512ecdbd33eca1576a7f82", MD: "7ac2776afb74f55bbc4f6eccf825ee13ac7445fb54974e6c24ebc0f03fdcd8530199a61106a31b4279e02201ee0f54fd"); + yield return (Msg: "da03486aa3cebbd6502e9f5a6f0f835e973a581befcc1aadefe7b3696ba71c70cd58c584", MD: "02c44ceec0bb7dc0f664ebe44230192b5b0bb646bb944d23fa1ff3586dc0523fa9d7f0dd6df5449ab9edd9a1096b07dc"); + yield return (Msg: "3c686d321ba66185cdca83ba9f41984fa61b826ef56b136e13f1239dadf6e03d877866ccb8", MD: "ad624edd9f2c3a32b56c53d9e813c01d66bcfe424c4a96907d52ac1ddd68370ec86dac67504a90e8a8e75502e01081d2"); + yield return (Msg: "4dcff99fac33840f6532547fb69b456902d6718fd5d4538e23462db6d00da61975f2b8e26298", MD: "cf37dd27997c1bb7e6dc405170066e74c6ce517c029ed8dce126d025da74e0b8e86da567e8d7d8d5b5d3e2a546df7489"); + yield return (Msg: "2799f672328834d7eaef9439795d35ce93c9094f58ded9f17c968a97a50a9e461489fed988e7f6", MD: "85cfc23c97cb13910b808e7033809a45aa0b7f7138de618c2ca622c8b813c988e264af3b96c7925dcbd1d2761757d800"); + yield return (Msg: "c7e947507822f28a562745a8fe6fed6cb47d73145804c894954e21245cde04fa9155a35904926aca", MD: "8bddf3baebbc5b04fe0b0a9c3c2b730abe918ce4892d2843c613ee96da0228512f0d1307c7d1a8922e79a92e957dd18e"); + yield return (Msg: "6c497bf6ff69cb39e3faa349212b8b6691ca237905ac0099c450b6d33abf362bedb65bdeb307bfea23", MD: "3639fab6191b35246278522cfacee0cd5b15580a26c505ae3c46b4b1c2572016b48f1b012bbbedec47916950fbb33a1d"); + yield return (Msg: "d15936f3b0c9018271812b4c81453c4457c7edd110bcea7f5735d6f5882d8f27155eb4cc285a65138ad6", MD: "0293eeef0aa3392c93d9c6ca89c08b317622572d4de2286a4b9ae6c2f9c9e0e64ee6c483d4f10859077e3c6868430214"); + yield return (Msg: "df18139f34b8904ef0681c1b7a3c86653e44b2535d6cecd1a2a17cd5b9357be79b85e5e04dd9eff2ca8b9a", MD: "db9e171d6e3336631c9ceec6b4d732ce62b015939269fb69fae7d22725500e8a2fc9f1459cf0a31fb9d16d7c44583f52"); + yield return (Msg: "0459dcbc149333ea2f937b779a5f3728148449a9aea3662cdd2cc653ce6a2050f9c0d54bf9326c039b263eb9", MD: "464ba409fbb45e985f84ee24662eb7c042c3c2ad9649f1ac4a8b2be9c07d37ed2e4284362057493f6a7e52c356b05bc5"); + yield return (Msg: "eb3f7002c8352270340b8da8643622e5f7e32cdb208a0dec06c6cb9e6b64cc4d8cb9de1d49397b3386464a25d1", MD: "a26bd76ce42d818dbec462d8fe7cdd957e6b84ae8750fb5e1c9c76bc6000e23737e073a59b4600e5056524edc667909d"); + yield return (Msg: "47e3e3d8c68ac9d9f4b3759d8c7d9dd901e35b096ee4c8b6cbe0cdf467463630926c08289abe153bfa1bcde3cd7c", MD: "b504ef475a568f9caba8352a0b2d243acdf3d2b41d8890a6fb3abb8aa28a29e0c7527d20e2d79b25b400ec27c314db72"); + yield return (Msg: "838d9c181c5ab59592723bd69360e0d7fd15232beada7591ea899ac78ffd53a32fc73a5fe522ed35d92a6e2bc148ca", MD: "53e99e1158d59032ffe4b5ea304c7d2f7a61b6b2a96ac97832ca26013549fe3f7dcdf926bd74ceabe4f1ff172daed6e6"); + yield return (Msg: "a90d2aa5b241e1ca9dab5b6dc05c3e2c93fc5a2210a6315d60f9b791b36b560d70e135ef8e7dba9441b74e53dab0606b", MD: "4a16881ce156f45fdfdb45088e3f23be1b4c5a7a6a35315d36c51c75f275733319aca185d4ab33130ffe45f751f1bbc5"); + yield return (Msg: "8c29345d3a091a5d5d71ab8f5a068a5711f7ba00b1830d5ed0bcdfb1bb8b03cd0af5fe78789c7314f289df7eee288735fe", MD: "e27b39a96255ff69c45285fca6edaaa3954ce32c1e3d9b1f60c1b6676594bb45caf0889fc11daf93a1b60746229689dd"); + yield return (Msg: "32876feefe9915a32399083472e3c3805ef261800b25582aa7c36395fd3ec05d47b49c4944bbcc2b8b5ebd081f63ae7943d0", MD: "f96433cdb69a607433ea2eb77d87d3328867dc4076b67ccf17f50f9e08e89a86624b60f2ecdb8affcd431fc13173fe75"); + yield return (Msg: "e2e77eb54f321f86f52ea3d3c8cdc3bc74d8b4f2f334591e5e63b781034da9d7b941d5827037dee40c58dc0d74c00996e582bc", MD: "a352ab33ca730482c376bdc573c9d1dc6d3597f9be9f798b74a57beaa8e9c57b78ee6761056eb67363e882fefcad4fb9"); + yield return (Msg: "da14b6d0b2ec4cf1e7c790e7f8f4212b8f4d05f50e75e2a56a5d70623c0d2e0115a15428129109b3b136d756e38a5c8463304290", MD: "aae7ad977e17ac0e560c0e0186433420f9fddcd191b9e91567cee05df88f1e1aee50424a313998a873f7a9c289a02217"); + yield return (Msg: "2db06f09abaa6a9e942d62741eacd0aa3b60d868bddf8717bef059d23f9efe170f8b5dc3ef87da3df361d4f12bfd720083a7a035e8", MD: "85d4e3e5abcb1b59ca6f551eb43b43ff64890511f73a9083a2ce6e9c2861c6e9664c765629024f4b01b0cd1594a5981b"); + yield return (Msg: "26bad23e51c4560c172076538b28716782ee6304962f68e27182048948d5c367a51a1c206a3e9b25135b40883b2e220f61cb5787ed8f", MD: "a44c7f84ab962f68283404f8c5c4029dbc35d2138e075c9327580baf89f292937bf99422e45756b3f942bf0a5ae4acb6"); + yield return (Msg: "77a9f652a003a83d22fb849b73fed7d37830c0dc53f89cea7dbec24e14f37197765206fe0e6672016e4dec4d9ebbe3e1b4423771a5d0a8", MD: "29c8bb39bb2aad419a00a80216ec71ec5ec9ab54c41927e3e3f2f48f079a5886d7fe89db98c807ab686d2339001d6252"); + yield return (Msg: "268c7b3a84849fec5c769bc4ad377dea10c9d20c91dd17fdbd9670a2fc909d0e212129ec40dee41dbf6194a3b04ae8be5e84ad5426ca4496", MD: "0dfc6ffcf4a387ec09ff862c6139a6f7ac77abb2b5e1f6dc814eb71525f8657ac74a7697c2975c70a543af0e227d03ca"); + yield return (Msg: "b8324341a6891a6b5e001a7d2ebba6e02e8335c124185309a4c9e9907c43bd8d4fa73c527fdf783650316dd24b148870e1436ac05111e9cdcc", MD: "6278d1cc17fb6d54129d04987d4774fa846dcac4ba8b6b72f41e63dc387ce0081ba29fb2c17c6744edae24e669cc9e75"); + yield return (Msg: "5ef8b3d79d299bee2c414560c7de626cc0d9fb429884aa69cc30095ef1f36b7e03a8ca25fb3601189f163b209e0facf8dc447f690b710fb47b72", MD: "7ec9505f33f4a5493574422de078e0490b61be8e8d6f158192bb7d2bdc2dc335598dc88d9b443cd1c14b883a77119df1"); + yield return (Msg: "ad7321c9a8b8f0bfe100811114270daad57f6e88772326b62d88a37a6f55c2cf9f759115ed6a590878e4dcefb592db151538db7de20229d26a181c", MD: "3782d2caa537294e809e9df837b1b07e2f1df07d0f4c12e12459f56eeaa478d5b3a41e519d9414eafa5ddd5661c831ba"); + yield return (Msg: "0719d9664541f0a824f71c83b809bb6afc973c9f7428e1ed11f7c29a558e1698b796aefb49eec2b098faf06bd43e82e1312bf0388c38a5bb523506d3", MD: "362c05f678df92883d56e19221391fb00d0f0afcec51d3e0feb15ba2fb60693b09d69118af649648933259d7b1e240ab"); + yield return (Msg: "5415c2596aa7d21e855be98491bd702357c19f21f46294f98a8aa37b3532ee1541ca35509adbef9d83eb99528ba14ef0bd2998a718da861c3f16fe6971", MD: "8f9fd7d879d6b51ee843e1fbcd40bb67449ae744db9f673e3452f028cb0189d9cb0fef7bdb5c760d63fea0e3ba3dd8d1"); + yield return (Msg: "b979a25a424b1e4c7ea71b6645545248498a2b8c4b568e4c8f3ff6e58d2ac8fbe97be4bea57d796b96041d1514511da5f6351120be7ab428107ef3c66921", MD: "e248a64b6ef112bf3d29948b1c995808e506c049f3906d74c3ee1e4d9f351658681901fe42c8e28024fe31014e2d342b"); + yield return (Msg: "e64c7bb9cd99ce547d43de3cc3b6f7d87a2df9d8a4760c18baf590c740ec53c89bfa075827e1f3f2858ce86f325077725e726103fbe94f7a1466c39f60924f", MD: "d1e5a72d2595f38714c6198ac14f8a5cdd894dcf9b4b8e975174b100df7bbf4f7ce291b4864f27c0b64e6330f6c1c82c"); + yield return (Msg: "91b7a1fd0e20072d9c5be7196e5eaf8df36fdf145895b30d4e4c02010d7c663499ac9d7a44732f4c7430511ba6fb0ae4b3dc9405523a054fdf962f5c5b79c423", MD: "07c2e0aeae30da83b5a6b320aa1cf727b10c2034583d7acda55648fa3daa017aa15588b6e2149101c56e3d7df7c76df1"); + yield return (Msg: "5bbc2d4efe63cbfc9fc221dd8d8384075a79c80a27d6a8c5219e677f4c5bb8338013dc2ab1770acf735d13c0bc704621ec2691350cf3ea2f53bded45ef8fc70702", MD: "dd0bbfe4b799642191abe316df9d59a3743566778b4459c51c3be3f658bdce45516ad188fbe1a8cad8a1fa78f8ebb645"); + yield return (Msg: "129549278e8976c38b5505815725400c3d2081edf141ad002e62ff299d9a0743f9c9f25971710b194dc88285d50b6cec6e140c19072f51cab32a9f6497abd3e407c6", MD: "ca26aec527fadcd5ebeb4eafa7c102f79a3c2edb452afd04f6162dd7a17bdd1aad7d616508a89a3ec6a40791d915acc8"); + yield return (Msg: "b9a9f378adeff4337bc7ec10d526c6dda07028375549f7fda7a81d05662c8a0da3b478f4152af42abb9f9a65c39da095abb8161ba6676b35411234bd466c2914e00370", MD: "99914f684e0b317f9338af0c71e9655a3af7153eb9fabaae61454bf8de9e0bfd274c1eff6c4b550e47afcb3b20fa7d9e"); + yield return (Msg: "101da5b09700dcadf80e5b7900f4e94c54d5f175569a854e488aa36fb41ab7220b0662178ca07a596768528123de3b2a3d944aa412875cedfeaf58dcc6d5b4a033a53b69", MD: "d3e32c9b271e11e4968397d85d76938b974ac1ba55bcbe8d7b7da02dbd7e3b9c9af0d98bbd7e50c436fcf9e3551e3432"); + yield return (Msg: "14761bbc5685b5de692973e2df7c9c4750889c19a952f912c817890546d5e37d940d13a14ac7925abbd875b8cd60e4920896ce6decc8db9f889da2b5489e1d110ff459d885", MD: "272222ed50631aff465c0e6fe49ecdfdca983bcb7231e50903e200b335b845108202c28315912c9c4fd50e2c6f13a9ea"); + yield return (Msg: "ed538009aeaed3284c29a6253702904967e0ea979f0a34a5f3d7b5ab886662da9b8e01efc4188e077c2cdeb5de0a8252aafbee948f86db62aae6e9e74abc89e6f6021a4db140", MD: "8361b680243b1661d6f1df53db363cae41c2ebb7438c00606d76b9c2a253faa1f09d6f520d69d692ec1dca0c7885119c"); + yield return (Msg: "c434d88468f1eda23848d0804b476933f24baeadec69743dd90d8455f1e1f290f6f1aaf3670c4c74f76d3ab83e9bef21ad8d9208c712ca478e70d5fb3c4bd48834c969dd38f484", MD: "9c26e96fcc09a76cc13d24ad25c9cef4300e96e97e4fb59b441baffed07f6a70b1464f2548c7fd7839810dbb9e9c1e18"); + yield return (Msg: "3064e5ba1e7751bf7198e0811ff4d4ca17d1311c25d9c3a316b562691cde75c974b0b52645c134ddcc709d77b6c1bd24cd684265d723c308bb4d0159e6b16d97ed9ceaa57436d302", MD: "1ea779739b204abe911b4923e6f60fece271eedfc7f074fe1919f0cbc6ce2a99234b003389520884b660165f5a1e80f8"); + yield return (Msg: "89d9521ad84b1c9afc2fbd0edc227193acd3330764b0d2cb71bf47c7aac946af85be13858b55976009f3b36b09ced4308052c817c9c4d0295225f61a9659a0874b88667cdcc5213919", MD: "4209bb8f869f6f17c8d5c368c489ac51a75e24a85a12de1b16fefc292ce636ff8fa360e82f05684f6b0b074ba370a933"); + yield return (Msg: "3216662da0227993d88288187177a0287de4eccf245d7c718b8045bbfb8869d93f1fb9e94d7478b0298e628c07e0edaab01dcf79264dc05f8b2181aa3f831dc949726fbcf80de4c9c9ed", MD: "64c45e018cfbc88f8f4ffe3cef0df3a94aab3049fafae28e28efbb2a4b94809eb302caf901010abfa194f72965663d35"); + yield return (Msg: "e776e6749c5b6c7def59cb98340984539280a9874f80412d4df0ee73d58acd1094d49ed4e35125834cf8cfe349e599144e4f2e200aba4fd3eb6d78cde027c1d5620e0270b5e83ab26b8d32", MD: "94bd67b7f2587b0bda5487cc45d00e4365f1ee40073cdf0d23a5ea3fba01eef42a46bfbac5306d67be02d8d918ae5c9a"); + yield return (Msg: "5d8f84b2f208b58a68e88ce8efb543a8404f0ec0c9805c760ad359d13faab84d3f8bb1d2a4bb45e72c0ec9245ffda2e572f94e466cffa44b876d5c5ed914d1ff338e06b74ad1e74d1405d23d", MD: "947350307748c29467f00103d0a07c3c228c5f494fc88fe2352ca5d10449d0dda7076780c05439a09694eb528d1f477a"); + yield return (Msg: "357d5765595065efe281afb8d021d4764fba091adde05e02af0a437051a04a3b8e552ec48fb7152c470412c40e40eec58b842842d8993a5ae1c61eb20de5112321bc97af618bbfbaf8e2a87699", MD: "32286970204c3451958f5155f090448f061dd81b136a14592a3204c6b08e922ee5bb6d6534dbf8efb4bb7387092c8400"); + yield return (Msg: "a8cb78e1485cbb7a9474c1c1f8e0f307cda5139a7e947df5ea20ac330a6dffcad4a9bd755f9f58724789eeee532615be550dd84f5241fde0e3058aeedbf287f02a460445027f5e6b3829bf71ecf4", MD: "51168bfeef8a981c0def0c4cb067baf15ce5feb8d5f7e9d6076b2836267391aee1fd3a0b5d3434ceb5cf2d6fa06fa063"); + yield return (Msg: "81acca82545e767ab59dcc750a09849cebad08ff31c9297f4fd510ebe6c27769938319180ccc66f36b1a7cf9c9f3538b0f6f371509f77cf0bc4d6d87facc85b933f2e27f8e1bf6cf388f80c0fcbfba", MD: "4ae44d6509986893a8414753b57d11f9c554d89c15ad6d70687c56c6c2ac73537acbb0d51f48e6bea6cf762d58890d7a"); + yield return (Msg: "94987498b1ca87a6f3fa4b999db726115c455d0ec24029b2f5810e49a94668864b8c470f7fc07c3dcd97f41c973b45ba4fa7879ee7546596881573b6863fc39d940eb3fa3444084f721341f5d23d2561", MD: "a733b118be72a187ddcbe5ba67e04b589f9cd9f8482c4bd9d64c580aba7d19d2d1f9c1ddf95fe6efdeffd44f67fcabb5"); + yield return (Msg: "de6b32c2d40d0659166db235259b530ea43f44e75d8b3e9e856ec4c1410bbea3696964af8b6c5dfd3304282369a4bc4e7cf66b91fecd0c7c105b59f1e0a496336f327440980a34614ee00fff2587d6b813", MD: "17ba30c0b5fc185b3245313b83dd0481145953101128914765784af751745b8a2b6a90a434548f3adaf1f07f18649890"); + yield return (Msg: "854211bedacc19f77b46cfa447a4ad672ea9b643f09f5cf5274ba28888207e2466b38127776fb976db8ad7165a378df6ee1e3a0f8109c9aff7e0d6126fd71333c6e6ebe15d7a65151d6a4a83b82c8a6f3149", MD: "ca85632a9f7c32ac4705c6458770025dda4fd07a8d5d6921b897b0da490d64400587649f2d20bf608b9a18d071b63b48"); + yield return (Msg: "822373d9d3d5b06a8da48a43095740fb98c9caf717350fd2c3b058024ff705b9346b7f0a495a6d4d93802bc45ece777f8c6a6e7c2ef6b8135115ff911a2ba5241665b6f7cbfa1b9d93b011b3aaa1dac1853fb2", MD: "6e84587c8c6e54353a6032e7505902ef7f0f0538dd1bb32922e13a7d4d98c47a541015381eab27e9186398120da7fb32"); + yield return (Msg: "c04b701f688092bbd1cf4217bc4b5877f2e60c087bdac46611482a61d51f820140403bc85be0c336332da0938734bde8c502014f3509266c73c6c93c22a1bd0ddf15a5ce7410c2894e9d092e32c079922ba1abb7", MD: "75c585503f15a526113608bc183180b1cb80f4d1b466c576bf021b1ce7a1528391f70e10446681849fa8a643cb2b6828"); + yield return (Msg: "009dd821cbed1235880fe647e191fe6f6555fdc98b8aad0ff3da5a6df0e5799044ef8e012ad54cb19a46fdd5c82f24f3ee77613d4bed961f6b7f4814aaac48bdf43c9234ce2e759e9af2f4ff16d86d5327c978dad5", MD: "02a09d37d31e4365c26bec0eaacecf29eea4e8d21ab915dd605248764d964f10ebb8fafdb591982d33869a1d08a7e313"); + yield return (Msg: "0b7dd6709d55e0d526d64c0c5af40acf595be353d705be7b7a0b1c4c83bbe6a1b1ec681f628e9d6cfc85ad9c8bb8b4ecac64c5b3a9b72f95e59afefa7bcec5be223a9b2b54836424afde52a29b22ab652d22cce34b39", MD: "5c84ae39d959b79555231746ad5b33689a31720ed0070f6772147977edd0aead07fb8b7b71b0bd587ebc5c1a80d564c7"); + yield return (Msg: "3e9b65d7bf4239420afa8639c8195b63902b24495b95c4143978e49843d88a92d1feed2eed1a88cd072d6d04ea26dce8ee4b14896fdb69bc7ff2971ed8ac5655148d2e9921218d74efdf17c56b533d0bb17d11e07d7458", MD: "ab7890d1b51af10285752bf9da5eee5c3e87a285dc33262d0261aa9a575f303e94845d7ab21b48f4e6884568cd78b550"); + yield return (Msg: "9436da433d1ebd10b946b129cb34bccec9b8f705aaba3f8561352ed36a8449aba2dd7ba15b1bc308b0c02913163af63a346524dff5521432db477f529606afb5d552efc95cb040db566b4d39eddaa19319e518a7b5c6931e", MD: "968ae9104f9c907c5a72936250dfedd62cd04f6e5ddd2c113490808a11884449aaef5d013ea3993a6cb6fc5c08754408"); + yield return (Msg: "37254bf9bc7cd4ed72e72b6bb623a0cc8eeb963d827aef65ad4bc54913235b6d3551533ce33421aa52ffbf186eb9a2787188eeb1b52ee645c6d4a631bc071415c80014940c28fbfeb0db472c326c8dacfd6ab21f3e225edef3", MD: "975e10fac9aa77b780e5f6c2151ec4a3c72ff26e41233cc774c074df1b78cce5af1191ba955a0bce15926ae691b0ffe7"); + yield return (Msg: "79e77cd08a6ef770bbe4bedf61557ea632b42d78637149670d4d6157d56ed7b2ccaee45d9439dcebc557b4118e86c15aa0ccc21c474b21abda1676cc56434d6d46422993e66dc99387dfa985358accf69884b9dd18a2c4d04448", MD: "94729f5f99a54f5a3ea69233ff9d522392d4596eb6ac2bbb07492ece3c67317412bb47ae317ddd20536c3adc003862f1"); + yield return (Msg: "64b76cb554f6becc238a3fcfc3eb97993667ec82fdc3fb28d42567709c3250c7997328aeddfdc2750451ac462281bf66fa94f4b8712c7a8342660574f20268e707c466627519c56259fea55be91e10faab3ad2ade6ce8b6557f202", MD: "26d48ef5067d704ee9e2a64e399de23068908b3c911ffc4056c168362c37385c92d37d51354b6505a82c4d22fec37eaa"); + yield return (Msg: "3df27829bfb1ab7d381f146b30370ef56b392b73b35b1be5d8bbcf88f499dda7f3c327b45350b8972991ee466545de96560cf451711fda884e3d9b2af3e909d655d25cee1c931beda79c40fa507097bdf1126771a7b9543ad5cb84b9", MD: "5fa4ebfa24150236c03409f0857b31cb95b0150f381c8858b01559957b1268f73c698709233e6b15468675a102d0c5e5"); + yield return (Msg: "b00f4e67ca08ccfa32b2698f70411d8f570f69c896e18ec8896cfe89551810543303f7df0c49f5b94783cce7df8d76d0b88d155633302d46003711f233339b1c9a8c20164ec8a328890a4932b7d90d92d023b548e4820558f8bd327010", MD: "eaa756b5892fdfc793d74e3f9f4d6c7a5a6a2241dd11e0c38ced59c8ec7be377a41d1d06774a5970ce9722d8e119d0ad"); + yield return (Msg: "a4f95f6a46a9cbf384a7e98e102d1fdc96839d1bf26b35a5a0bd6cb9734fd17e8a178d4581943c0fe469fb4fe94cc2f15e1ef59ae05b35324eb57ca07dfc69d42d41d80b3c3bb64e1aea143c7d79790a56697dc803ec93e6c68f27f6761c", MD: "1aff8d9c64f0c162ed0195d1f3a342a010d14be0636903c48020ba42de1cfa8b98ae2142d89af3e69e9eb4c735857dd1"); + yield return (Msg: "02713084bf93fdc35135515243c3bc0f4b2b447f2d3461c0dc104cbfe23479ab036762a91d1987c953f7b3386abc80b8734a1d4eabf94f3a9f2fb62c943152b5253846fc2ec8dbb2e93dc74857a7b05fe2d7ec8040ba8b0d9ae69777ee739a", MD: "84da02114e341a3636f00822b32bd21a8a1f7b39f2956bd97f39346fedf9aae63b304c65c93a541e8bcda549576d5f27"); + yield return (Msg: "00ce225eaea24843406fa42cc8450e66f76ac9f549b8591f7d40942f4833fc734a034c8741c551d57ddafb5d94ceb4b25680f045038306e6bcc53e88386e2b45b80b3ba23dec8c13f8ca01c202ae968c4d0df04cdb38395d2df42a5aff646928", MD: "81d6e0d96575a9b8ca083ee9ec2ead57ddf72b97d7709086a2f4a749d3f61d16423463487562c7f09aba1b26e8cae47b"); + yield return (Msg: "7af3feed9b0f6e9408e8c0397c9bb671d0f3f80926d2f48f68d2e814f12b3d3189d8174897f52a0c926ccf44b9d057cc04899fdc5a32e48c043fd99862e3f761dc3115351c8138d07a15ac23b8fc5454f0373e05ca1b7ad9f2f62d34caf5e1435c", MD: "00e95f4e8a32a03e0a3afba0fd62c7c3c7120b41e297a7ff14958c0bdf015a478f7bab9a22082bfb0d206e88f4685117"); + yield return (Msg: "2eae76f4e7f48d36cd83607813ce6bd9ab0ecf846ad999df67f64706a4708977f0e9440f0b31dc350c17b355007fed90d4b577b175014763357ce5a271212a70702747c98f8f0ad89bf95d6b7fbb10a51f34d8f2835e974038a3dd6df3f2affb7811", MD: "eb396cfaf26ee2775af3c9a3a3047664ca34cbc228ccbb966df187d518717df6a328ecc316ed0ed09b170080eccc486f"); + yield return (Msg: "093e56d33bd9337ad2ad268d14bac69a64a8a7361350cf9f787e69a043f5beb50eb460703578a81be882639f7e9ac9a50c54affa3792fd38464a61a37c8a4551a4b9ff8eed1f487ef8a8f00430e4d0e35a53ff236ce049b7a3abdc5cd00b45c4f3d49b", MD: "4a339128486e5b274fc4ed538c0ec9e57f780e9c500c5f92b04ae81a22fbeebf3785259a0bb3b6d9b47f31873cd8dffa"); + yield return (Msg: "0593babe7a6202077c026e253cb4c60ee7bad7b1c31a20da7aa0ce56b622eb57ed07d21a7f0ae6c6fe3c8398cc48353decfb287f1204e024fcf82a13059953b9f85797ab2217dc8dab34a13226c33104661c1ca79396e7d97e91039d32bafc98cc8af3bb", MD: "5981815c1618cc49cd5cf71a4b7b32b8cd7b7ef553bfaef2149ac723ff2582a2d345c5bd05943e155ced1e5f091c5601"); + yield return (Msg: "ae1828047c5f82a7b9712f3399832124b892f2f7aea51c8fe3536cd6a584b4a7777cc1ecac158c03354bb467b8fe2c8ce2f4310afd1e80fec51cc5ad7702566b2c5d21bc6571e4b8e7c59cb4c9e23f1ecb57ada9e900e4aa308874c2d12d34be74c332bbce", MD: "7257f5bfa7d33d1cf5f4550d0cb78750e84c5b7d25027da6acec64bdf30879a0e5c97fe7c468e743aa5ec2bddb29d193"); + yield return (Msg: "3bceedf5df8fe699871decb7dd48203e2518fb0fce0f865f46adce5c133a921320bf40915456204869a3ceb5fca3ed40e0a41a64b8951f0fc580694cfc55bd1f5ce926b07e3e32ac6e055de9b961ce49c7ee41e06b024559b933a79518192e969855889c85d1", MD: "60d7f8bd85fb7a13701db5aded2b7771ab5e476ec34f1fd4298978defbd2b31bb2979391559a164b3ed28f6a39031a11"); + yield return (Msg: "6c36147652e71b560becbca1e7656c81b4f70bece26321d5e55e67a3db9d89e26f2f2a38fd0f289bf7fa22c2877e38d9755412794cef24d7b855303c332e0cb5e01aa50bb74844f5e345108d6811d5010978038b699ffaa370de8473f0cda38b89a28ed6cabaf6", MD: "b1319192df11faa00d3c4b068becc8f1ba3b00e0d1ff1f93c11a3663522fdb92ab3cca389634687c632e0a4b5a26ce92"); + yield return (Msg: "92c41d34bd249c182ad4e18e3b856770766f1757209675020d4c1cf7b6f7686c8c1472678c7c412514e63eb9f5aee9f5c9d5cb8d8748ab7a5465059d9cbbb8a56211ff32d4aaa23a23c86ead916fe254cc6b2bff7a9553df1551b531f95bb41cbbc4acddbd372921", MD: "71307eec1355f73e5b726ed9efa1129086af81364e30a291f684dfade693cc4bc3d6ffcb7f3b4012a21976ff9edcab61"); + + // First 5 from SHA3_384LongMsg.rsp + yield return ( + Msg: + "5fe35923b4e0af7dd24971812a58425519850a506dfa9b0d254795be785786c319a2567cbaa5e35bcf8fe83d943e23fa5169b73adc1fcf8b607084b15e6a013df147e46256e4e803ab75c110f77848136be7d806e8b2f868c16c3a90c14463407038cb7d9285079e" + + "f162c6a45cedf9c9f066375c969b5fcbcda37f02aacff4f31cded3767570885426bebd9eca877e44674e9ae2f0c24cdd0e7e1aaf1ff2fe7f80a1c4f5078eb34cd4f06fa94a2d1eab5806ca43fd0f06c60b63d5402b95c70c21ea65a151c5cfaf8262a46be3c72226" + + "4b", + MD: "3054d249f916a6039b2a9c3ebec1418791a0608a170e6d36486035e5f92635eaba98072a85373cb54e2ae3f982ce132b"); + + yield return ( + Msg: + "035adcb639e5f28bb5c88658f45c1ce0be16e7dafe083b98d0ab45e8dcdbfa38e3234dfd973ba555b0cf8eea3c82ae1a3633fc565b7f2cc839876d3989f35731be371f60de140e3c916231ec780e5165bf5f25d3f67dc73a1c33655dfdf439dfbf1cbba8b779158a" + + "810ad7244f06ec078120cd18760af436a238941ce1e687880b5c879dc971a285a74ee85c6a746749a30159ee842e9b03f31d613dddd22975cd7fed06bd049d772cb6cc5a705faa734e87321dc8f2a4ea366a368a98bf06ee2b0b54ac3a3aeea637caebe70ad09ccd" + + "a93cc06de95df73394a87ac9bbb5083a4d8a2458e91c7d5bf113aecae0ce279fdda76ba690787d26345e94c3edbc16a35c83c4d071b132dd81187bcd9961323011509c8f644a1c0a3f14ee40d7dd186f807f9edc7c02f6761061bbb6dd91a6c96ec0b9f10edbbd29" + + "dc52", + MD: "02535d86cc7518484a2a238c921b739b1704a50370a2924abf39958c5976e658dc5e87440063112459bddb40308b1c70"); + + yield return ( + Msg: + "7f25b2c0eb1a6911cc3328fcdcd40f28f010375f7b1b51a05402896fb999b17093b59b34fb9cc653feba3dbb9d96bd47180416946d9bd3101b691d532be6ddb3712721121054c1fb3c5c42ee44e7faf7cf8d75856545187a3220047f07373e9aa2e10c022f2aa232" + + "0f81fd3cd7b110609c131edd6e016707228d069a55731a4ead4d24ab6206b01ffd91384e60db45a907fed7428db707de721aeb4c1b84baf61ad230b6b0d034eb90f4b9cbe64de2fb98b6695dcc4f4129aa2e7a3f635166bb72d7faca227076bd5013495c72ef2e7d" + + "d8a39cd532b15d0d53307c1834c265c53cc64890becfbebec454afa90ba973584e2d3752c7c6a3b4f48aba8297bf013b0006e3b08ed354157420b559b963f7b383bd047e94745a4615a3f9239230804547ff93d19a657fece8e02114840504b7fdb9c9fea0a4ccea" + + "3ee304a330fd2b0d97191f9be86e8968a9fabc847577e08b468b4f7df43f3fc9f8b2a2ab760f4ab87bbc51b883d4b8b33ed84e4f93a1d359e6995ea1962bfc0bca789ae36e4c25717850efcd708155f52fe09f1de76b2746634dbe1290524bd73d9db5f21f9d035e" + + "183dc2", + MD: "927962c873a69caa05cadc1cb485eb1cbb07748e47d942192df4af9233f42b95a638918306ae83a8237d21c2824f666d"); + + yield return ( + Msg: + "386f98670b177683d0b804c5875fe9c7afa233ee66349c9fd1b60bb0becf5e1d887e67fd3baf34b4f90d94699d18d6bb9d77d4af358f31edc254de2d6c5fe3ec07425c633b18c1b9e3606b78b40b543e1fd31fb578cf58c45744fc073fbf3c7d7d607e815379a5fc" + + "565892d81560eab8fb5f1ae6771b998c592e6d288014f13ab283d53fcbfa66e31a9d107308402191fac2cf2b799c7dae91b93a7676898b8a6e516a86eac58ed8f6d8ed2fd4d38031e4a4466dc8798b90c48e6adb6b4391d47872443cfaffa542b4b132f6c3408f00" + + "81af8692aadb4c9bbd55053ea56d8b82998f6b4b41d331891acfe6af1bb0d6679989978368ea463743b514866d2d01fb9950e8990867bc14f1db1142254adeccf3da812949cd03cd1d569e9d0bab7ca7405cc21096e3cd4d007cbb9629372e98584b4c6b97ad0bc3" + + "14e1ab6ac71184ee555c01973570ed9b115bed956f9e4e349083013098b1e483f0fe44d5e9849f38a2f7ae152b36a266ea1faf263ea8c706632ba8629602187379546fc6b82e57ededd6d074c15c771754710731e07c207899eb47e8d7c72ffd768c36257d373375" + + "ffa06f9b3f0af11417f9ff9f9b44e1f1f96ae8aaa429af88b14da1da81c7bb38a0fe9372ed6a9ac6fb5e9e56b82593d94c5192904450227bf040b7ce0904789f979845e112a1f995c849ec3f7e49bd975a474e8201630f40fc0d80e76019f110ae158cd0f8da96ea" + + "4561f242", + MD: "d30ec9a7baeabe40f6648a624dddf8721c89542e258f0fa9afcc9e68433faef781824048b0b771a94e8f0c17a403f9fb"); + + yield return ( + Msg: + "8c569727f1d4548f1c66a5c830346259612d10c5fef90518ae2fcdbffac9cd9c0bd5265ab56ddcfeb5e838bf37526a189c1a731b790b4208e37d1d1eeacd43b1630ad07debf1e03a281cf7715276a18df2f25535ea7d9fd9b6317f8bf1cb0c111b5f5c38994aa86b" + + "fd69ac8388884de1ed1d7eba583764b3afb1b8ae18ab6ee3bb3a9432c95f7cb7bd361da0e270b73b1503b653cc20d9bd5766932e6655b250cc053e148218a449efed136e661627c4f10dc5a84d22462035b8d7b4e4b11f7fd5272385cd5d67471bf556951e63e4a4" + + "09a17260e324f203d2104be798a8ff985e080b2eb1160fdacab6aebe123d3802e5298624960f268fb4d4b9708c2098c5ef10beb6362be2298298e391498e69060e0bca9b6fc92aec656ee7f6c802342c11a703c76484295dce03bcb5cb3cc0da0bb1036e753b4641" + + "6d449d22523719f54b35a306440a2b9d335f03d3a03085a36481fc44b14dc2b652c0a59c34a68f492622671ddda332123b147e92d153008ca2e57cc629e8e5759e48c60b7636e05029d614b4373884e36d8af69b648c79ba4c444a9ce7f2f8a3d846c7171ed15231" + + "dcba75725bb26a395129329564c23758ea052f6df355436b89217169365e2f15c734510050f72c3c705afc29d6df838c0492f3e153f70ef338418ca9c5c4bd2373ad6f051ef1121351831affc4caa57e23525ea111c2a1636d0ee07fd4ed4584678e982ace8664e7" + + "7d0e55be356be558cead3755359c43e4b1f034916ac00e5f2b3d941767a069df7a61750e32aa8a3f8e0b48a5c56f3e9e8a4f518a8f2562dd48242b73f1266a24d2e64299c26fde5dead45737cb22d8b8839300104b04872645a925e77500afdd0c038404eda227da" + + "6a702db64e", + MD: "91e24f999cac1b9ab9ae456ecf47b52c1144ffd1df2d95feb05fce930e37ff767a005cf07bb7af45c8a73585e8544965"); + } + } + } +} diff --git a/src/libraries/System.Security.Cryptography/tests/Sha3_512Tests.cs b/src/libraries/System.Security.Cryptography/tests/Sha3_512Tests.cs new file mode 100644 index 00000000000000..84b057436e7fc8 --- /dev/null +++ b/src/libraries/System.Security.Cryptography/tests/Sha3_512Tests.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.IO; +using System.Threading; +using System.Threading.Tasks; +using Xunit; + +namespace System.Security.Cryptography.Tests +{ + public class SHA3_512Tests : HashAlgorithmTestDriver + { + public sealed class Traits : IHashTrait + { + public static bool IsSupported => SHA3_512.IsSupported; + public static int HashSizeInBytes => SHA3_512.HashSizeInBytes; + } + + protected override HashAlgorithm Create() + { + return SHA3_512.Create(); + } + + protected override bool TryHashData(ReadOnlySpan source, Span destination, out int bytesWritten) + { + return SHA3_512.TryHashData(source, destination, out bytesWritten); + } + + protected override byte[] HashData(byte[] source) => SHA3_512.HashData(source); + + protected override byte[] HashData(ReadOnlySpan source) => SHA3_512.HashData(source); + + protected override int HashData(ReadOnlySpan source, Span destination) => + SHA3_512.HashData(source, destination); + + protected override int HashData(Stream source, Span destination) => + SHA3_512.HashData(source, destination); + + protected override byte[] HashData(Stream source) => SHA3_512.HashData(source); + + protected override ValueTask HashDataAsync(Stream source, Memory destination, CancellationToken cancellationToken) => + SHA3_512.HashDataAsync(source, destination, cancellationToken); + + protected override ValueTask HashDataAsync(Stream source, CancellationToken cancellationToken) => + SHA3_512.HashDataAsync(source, cancellationToken); + + [ConditionalFact(nameof(IsSupported))] + public void SHA3_512_Kats() + { + foreach ((string Msg, string MD) kat in Fips202Kats) + { + Verify(Convert.FromHexString(kat.Msg), kat.MD); + } + } + + [ConditionalFact(nameof(IsSupported))] + public void SHA3_512_Empty_Stream() + { + VerifyRepeating( + "", + 0, + "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"); + } + + [ConditionalFact(nameof(IsSupported))] + public async Task SHA3_512_Empty_Stream_Async() + { + await VerifyRepeatingAsync( + "", + 0, + "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"); + } + + [ConditionalFact(nameof(IsSupported))] + public void SHA3_512_VerifyLargeStream_MultipleOf4096() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl dgst -sha3-512 + VerifyRepeating( + "0102030405060708", + 1024, + "b5ec7fe7061c944b65f42a3193ebafcc3b35f063dc2ac7a5af05140b2439c425e4d9e63bc97103f704a7b6849a1986cec743ac288ca2f123e82c0ce60b714615"); + } + + [ConditionalFact(nameof(IsSupported))] + public void SHA3_512_VerifyLargeStream_NotMultipleOf4096() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl dgst -sha3-512 + VerifyRepeating( + "0102030405060708", + 1025, + "ea418b3d279a9b25ddc6f8a294006c63068cbd4b872163365f7d11f6f287c8291adc0e3b77999db9606a40c989d7eca405247162104feec1d5a46e59404692a2"); + } + + [ConditionalFact(nameof(IsSupported))] + public async Task SHA3_512_VerifyLargeStream_NotMultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1025}; do echo -n "0102030405060708"; done | openssl dgst -sha3-512 + await VerifyRepeatingAsync( + "0102030405060708", + 1025, + "ea418b3d279a9b25ddc6f8a294006c63068cbd4b872163365f7d11f6f287c8291adc0e3b77999db9606a40c989d7eca405247162104feec1d5a46e59404692a2"); + } + + [ConditionalFact(nameof(IsSupported))] + public async Task SHA3_512_VerifyLargeStream_MultipleOf4096_Async() + { + // Verfied with: + // for _ in {1..1024}; do echo -n "0102030405060708"; done | openssl dgst -sha3-512 + await VerifyRepeatingAsync( + "0102030405060708", + 1024, + "b5ec7fe7061c944b65f42a3193ebafcc3b35f063dc2ac7a5af05140b2439c425e4d9e63bc97103f704a7b6849a1986cec743ac288ca2f123e82c0ce60b714615"); + } + + [Fact] + public void SHA3_512_HashSizes() + { + Assert.Equal(512, SHA3_512.HashSizeInBits); + Assert.Equal(64, SHA3_512.HashSizeInBytes); + } + + [Fact] + public void SHA3_512_IsSupported_AgreesWithPlatformVersion() + { + Assert.Equal(PlatformDetection.SupportsSha3, SHA3_512.IsSupported); + } + + private static IEnumerable<(string Msg, string MD)> Fips202Kats + { + get + { + // Generated from SHA3_512ShortMsg.rsp + yield return (Msg: "", MD: "a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26"); + yield return (Msg: "e5", MD: "150240baf95fb36f8ccb87a19a41767e7aed95125075a2b2dbba6e565e1ce8575f2b042b62e29a04e9440314a821c6224182964d8b557b16a492b3806f4c39c1"); + yield return (Msg: "ef26", MD: "809b4124d2b174731db14585c253194c8619a68294c8c48947879316fef249b1575da81ab72aad8fae08d24ece75ca1be46d0634143705d79d2f5177856a0437"); + yield return (Msg: "37d518", MD: "4aa96b1547e6402c0eee781acaa660797efe26ec00b4f2e0aec4a6d10688dd64cbd7f12b3b6c7f802e2096c041208b9289aec380d1a748fdfcd4128553d781e3"); + yield return (Msg: "fc7b8cda", MD: "58a5422d6b15eb1f223ebe4f4a5281bc6824d1599d979f4c6fe45695ca89014260b859a2d46ebf75f51ff204927932c79270dd7aef975657bb48fe09d8ea008e"); + yield return (Msg: "4775c86b1c", MD: "ce96da8bcd6bc9d81419f0dd3308e3ef541bc7b030eee1339cf8b3c4e8420cd303180f8da77037c8c1ae375cab81ee475710923b9519adbddedb36db0c199f70"); + yield return (Msg: "71a986d2f662", MD: "def6aac2b08c98d56a0501a8cb93f5b47d6322daf99e03255457c303326395f765576930f8571d89c01e727cc79c2d4497f85c45691b554e20da810c2bc865ef"); + yield return (Msg: "ec83d707a1414a", MD: "84fd3775bac5b87e550d03ec6fe4905cc60e851a4c33a61858d4e7d8a34d471f05008b9a1d63044445df5a9fce958cb012a6ac778ecf45104b0fcb979aa4692d"); + yield return (Msg: "af53fa3ff8a3cfb2", MD: "03c2ac02de1765497a0a6af466fb64758e3283ed83d02c0edb3904fd3cf296442e790018d4bf4ce55bc869cebb4aa1a799afc9d987e776fef5dfe6628e24de97"); + yield return (Msg: "3d6093966950abd846", MD: "53e30da8b74ae76abf1f65761653ebfbe87882e9ea0ea564addd7cfd5a6524578ad6be014d7799799ef5e15c679582b791159add823b95c91e26de62dcb74cfa"); + yield return (Msg: "1ca984dcc913344370cf", MD: "6915ea0eeffb99b9b246a0e34daf3947852684c3d618260119a22835659e4f23d4eb66a15d0affb8e93771578f5e8f25b7a5f2a55f511fb8b96325ba2cd14816"); + yield return (Msg: "fc7b8cdadebe48588f6851", MD: "c8439bb1285120b3c43631a00a3b5ac0badb4113586a3dd4f7c66c5d81012f7412617b169fa6d70f8e0a19e5e258e99a0ed2dcfa774c864c62a010e9b90ca00d"); + yield return (Msg: "ecb907adfb85f9154a3c23e8", MD: "94ae34fed2ef51a383fb853296e4b797e48e00cad27f094d2f411c400c4960ca4c610bf3dc40e94ecfd0c7a18e418877e182ca3ae5ca5136e2856a5531710f48"); + yield return (Msg: "d91a9c324ece84b072d0753618", MD: "fb1f06c4d1c0d066bdd850ab1a78b83296eba0ca423bb174d74283f46628e6095539214adfd82b462e8e9204a397a83c6842b721a32e8bb030927a568f3c29e6"); + yield return (Msg: "c61a9188812ae73994bc0d6d4021", MD: "069e6ab1675fed8d44105f3b62bbf5b8ff7ae804098986879b11e0d7d9b1b4cb7bc47aeb74201f509ddc92e5633abd2cbe0ddca2480e9908afa632c8c8d5af2a"); + yield return (Msg: "a6e7b218449840d134b566290dc896", MD: "3605a21ce00b289022193b70b535e6626f324739542978f5b307194fcf0a5988f542c0838a0443bb9bb8ff922a6a177fdbd12cf805f3ed809c48e9769c8bbd91"); + yield return (Msg: "054095ba531eec22113cc345e83795c7", MD: "f3adf5ccf2830cd621958021ef998252f2b6bc4c135096839586d5064a2978154ea076c600a97364bce0e9aab43b7f1f2da93537089de950557674ae6251ca4d"); + yield return (Msg: "5b1ec1c4e920f5b995b6a788b6e989ac29", MD: "135eea17ca4785482c19cd668b8dd2913216903311fa21f6b670b9b573264f8875b5d3c071d92d63556549e523b2af1f1a508bd1f105d29a436f455cd2ca1604"); + yield return (Msg: "133b497b00932773a53ba9bf8e61d59f05f4", MD: "783964a1cf41d6d210a8d7c81ce6970aa62c9053cb89e15f88053957ecf607f42af08804e76f2fbdbb31809c9eefc60e233d6624367a3b9c30f8ee5f65be56ac"); + yield return (Msg: "88c050ea6b66b01256bda299f399398e1e3162", MD: "6bf7fc8e9014f35c4bde6a2c7ce1965d9c1793f25c141021cc1c697d111363b3854953c2b4009df41878b5558e78a9a9092c22b8baa0ed6baca005455c6cca70"); + yield return (Msg: "d7d5363350709e96939e6b68b3bbdef6999ac8d9", MD: "7a46beca553fffa8021b0989f40a6563a8afb641e8133090bc034ab6763e96d7b7a0da4de3abd5a67d8085f7c28b21a24aefb359c37fac61d3a5374b4b1fb6bb"); + yield return (Msg: "54746a7ba28b5f263d2496bd0080d83520cd2dc503", MD: "d77048df60e20d03d336bfa634bc9931c2d3c1e1065d3a07f14ae01a085fe7e7fe6a89dc4c7880f1038938aa8fcd99d2a782d1bbe5eec790858173c7830c87a2"); + yield return (Msg: "73df7885830633fc66c9eb16940b017e9c6f9f871978", MD: "0edee1ea019a5c004fd8ae9dc8c2dd38d4331abe2968e1e9e0c128d2506db981a307c0f19bc2e62487a92992af77588d3ab7854fe1b68302f796b9dcd9f336df"); + yield return (Msg: "14cb35fa933e49b0d0a400183cbbea099c44995fae1163", MD: "af2ef4b0c01e381b4c382208b66ad95d759ec91e386e953984aa5f07774632d53b581eba32ed1d369c46b0a57fee64a02a0e5107c22f14f2227b1d11424becb5"); + yield return (Msg: "75a06869ca2a6ea857e26e78bb78a139a671ccb098d8205a", MD: "88be1934385522ae1d739666f395f1d7f99978d62883a261adf5d618d012dfab5224575634446876b86b3e5f7609d397d338a784b4311027b1024ddfd4995a0a"); + yield return (Msg: "b413ab364dd410573b53f4c2f28982ca07061726e5d999f3c2", MD: "289e889b25f9f38facfccf3bdbceea06ef3baad6e9612b7232cd553f4884a7a642f6583a1a589d4dcb2dc771f1ff6d711b85f731145a89b100680f9a55dcbb3f"); + yield return (Msg: "d7f9053984213ebabc842fd8ce483609a9af5dc140ecdbe63336", MD: "f167cb30e4bacbdc5ed53bc615f8c9ea19ad4f6bd85ca0ff5fb1f1cbe5b576bda49276aa5814291a7e320f1d687b16ba8d7daab2b3d7e9af3cd9f84a1e9979a1"); + yield return (Msg: "9b7f9d11be48e786a11a472ab2344c57adf62f7c1d4e6d282074b6", MD: "82fa525d5efaa3cce39bffef8eee01afb52067097f8965cde71703345322645eae59dbaebed0805693104dfb0c5811c5828da9a75d812e5562615248c03ff880"); + yield return (Msg: "115784b1fccfabca457c4e27a24a7832280b7e7d6a123ffce5fdab72", MD: "ec12c4ed5ae84808883c5351003f7e26e1eaf509c866b357f97472e5e19c84f99f16dbbb8bfff060d6c0fe0ca9c34a210c909b05f6a81f441627ce8e666f6dc7"); + yield return (Msg: "c3b1ad16b2877def8d080477d8b59152fe5e84f3f3380d55182f36eb5f", MD: "4b9144edeeec28fd52ba4176a78e080e57782d2329b67d8ac8780bb6e8c2057583172af1d068922feaaff759be5a6ea548f5db51f4c34dfe7236ca09a67921c7"); + yield return (Msg: "4c66ca7a01129eaca1d99a08dd7226a5824b840d06d0059c60e97d291dc4", MD: "567c46f2f636223bd5ed3dc98c3f7a739b42898e70886f132eac43c2a6fadabe0dd9f1b6bc4a9365e5232295ac1ac34701b0fb181d2f7f07a79d033dd426d5a2"); + yield return (Msg: "481041c2f56662316ee85a10b98e103c8d48804f6f9502cf1b51cfa525cec1", MD: "46f0058abe678195b576df5c7eb8d739468cad1908f7953ea39c93fa1d96845c38a2934d23804864a8368dae38191d983053ccd045a9ab87ef2619e9dd50c8c1"); + yield return (Msg: "7c1688217b313278b9eae8edcf8aa4271614296d0c1e8916f9e0e940d28b88c5", MD: "627ba4de74d05bb6df8991112e4d373bfced37acde1304e0f664f29fa126cb497c8a1b717b9929120883ec8898968e4649013b760a2180a9dc0fc9b27f5b7f3b"); + yield return (Msg: "785f6513fcd92b674c450e85da22257b8e85bfa65e5d9b1b1ffc5c469ad337d1e3", MD: "5c11d6e4c5c5f76d26876c5976b6f555c255c785b2f28b6700ca2d8b3b3fa585636239277773330f4cf8c5d5203bcc091b8d47e7743bbc0b5a2c54444ee2acce"); + yield return (Msg: "34f4468e2d567b1e326c0942970efa32c5ca2e95d42c98eb5d3cab2889490ea16ee5", MD: "49adfa335e183c94b3160154d6698e318c8b5dd100b0227e3e34cabea1fe0f745326220f64263961349996bbe1aae9054de6406e8b350408ab0b9f656bb8daf7"); + yield return (Msg: "53a0121c8993b6f6eec921d2445035dd90654add1298c6727a2aed9b59bafb7dd62070", MD: "918b4d92e1fcb65a4c1fa0bd75c562ac9d83186bb2fbfae5c4784de31a14654546e107df0e79076b8687bb3841c83ba9181f9956cd43428ba72f603881b33a71"); + yield return (Msg: "d30fa4b40c9f84ac9bcbb535e86989ec6d1bec9b1b22e9b0f97370ed0f0d566082899d96", MD: "39f104c1da4af314d6bceb34eca1dfe4e67484519eb76ba38e4701e113e6cbc0200df86e4439d674b0f42c72233360478ba5244384d28e388c87aaa817007c69"); + yield return (Msg: "f34d100269aee3ead156895e8644d4749464d5921d6157dffcbbadf7a719aee35ae0fd4872", MD: "565a1dd9d49f8ddefb79a3c7a209f53f0bc9f5396269b1ce2a2b283a3cb45ee3ae652e4ca10b26ced7e5236227006c94a37553db1b6fe5c0c2eded756c896bb1"); + yield return (Msg: "12529769fe5191d3fce860f434ab1130ce389d340fca232cc50b7536e62ad617742e022ea38a", MD: "daee10e815fff0f0985d208886e22f9bf20a3643eb9a29fda469b6a7dcd54b5213c851d6f19338d63688fe1f02936c5dae1b7c6d5906a13a9eeb934400b6fe8c"); + yield return (Msg: "b2e3a0eb36bf16afb618bfd42a56789179147effecc684d8e39f037ec7b2d23f3f57f6d7a7d0bb", MD: "04029d6d9e8e394afa387f1d03ab6b8a0a6cbab4b6b3c86ef62f7142ab3c108388d42cb87258b9e6d36e5814d8a662657cf717b35a5708365e8ec0396ec5546b"); + yield return (Msg: "25c4a5f4a07f2b81e0533313664bf615c73257e6b2930e752fe5050e25ff02731fd2872f4f56f727", MD: "ec2d38e5bb5d7b18438d5f2029c86d05a03510db0e66aa299c28635abd0988c58be203f04b7e0cc25451d18f2341cd46f8705d46c2066dafab30d90d63bf3d2c"); + yield return (Msg: "134bb8e7ea5ff9edb69e8f6bbd498eb4537580b7fba7ad31d0a09921237acd7d66f4da23480b9c1222", MD: "8f966aef96831a1499d63560b2578021ad970bf7557b8bf8078b3e12cefab122fe71b1212dc704f7094a40b36b71d3ad7ce2d30f72c1baa4d4bbccb3251198ac"); + yield return (Msg: "f793256f039fad11af24cee4d223cd2a771598289995ab802b5930ba5c666a24188453dcd2f0842b8152", MD: "22c3d9712535153a3e206b1033929c0fd9d937c39ba13cf1a6544dfbd68ebc94867b15fda3f1d30b00bf47f2c4bf41dabdeaa5c397dae901c57db9cd77ddbcc0"); + yield return (Msg: "23cc7f9052d5e22e6712fab88e8dfaa928b6e015ca589c3b89cb745b756ca7c7634a503bf0228e71c28ee2", MD: "6ecf3ad6064218ee101a555d20fab6cbeb6b145b4eeb9c8c971fc7ce05581a34b3c52179590e8a134be2e88c7e549875f4ff89b96374c6995960de3a5098cced"); + yield return (Msg: "a60b7b3df15b3f1b19db15d480388b0f3b00837369aa2cc7c3d7315775d7309a2d6f6d1371d9c875350dec0a", MD: "8d651605c6b32bf022ea06ce6306b2ca6b5ba2781af87ca2375860315c83ad88743030d148ed8d73194c461ec1e84c045fc914705747614c04c8865b51da94f7"); + yield return (Msg: "2745dd2f1b215ea509a912e5761cccc4f19fa93ba38445c528cb2f099de99ab9fac955baa211fd8539a671cdb6", MD: "4af918eb676ce278c730212ef79d818773a76a43c74d643f238e9b61acaf4030c617c4d6b3b7514c59b3e5e95d82e1e1e35443e851718b13b63e70b123d1b72c"); + yield return (Msg: "88adee4b46d2a109c36fcfb660f17f48062f7a74679fb07e86cad84f79fd57c86d426356ec8e68c65b3caa5bc7ba", MD: "6257acb9f589c919c93c0adc4e907fe011bef6018fbb18e618ba6fcc8cbc5e40641be589e86dbb0cf7d7d6bf33b98d8458cce0af7857f5a7c7647cf350e25af0"); + yield return (Msg: "7d40f2dc4af3cfa12b00d64940dc32a22d66d81cb628be2b8dda47ed6728020d55b695e75260f4ec18c6d74839086a", MD: "5c46c84a0a02d898ed5885ce99c47c77afd29ae015d027f2485d630f9b41d00b7c1f1faf6ce57a08b604b35021f7f79600381994b731bd8e6a5b010aeb90e1eb"); + yield return (Msg: "3689d8836af0dc132f85b212eb670b41ecf9d4aba141092a0a8eca2e6d5eb0ba4b7e61af9273624d14192df7388a8436", MD: "17355e61d66e40f750d0a9a8e8a88cd6f9bf6070b7efa76442698740b4487ea6c644d1654ef16a265204e03084a14cafdccf8ff298cd54c0b4009967b6dd47cc"); + yield return (Msg: "58ff23dee2298c2ca7146227789c1d4093551047192d862fc34c1112d13f1f744456cecc4d4a02410523b4b15e598df75a", MD: "aca89aa547c46173b4b2a380ba980da6f9ac084f46ac9ddea5e4164aeef31a9955b814a45aec1d8ce340bd37680952c5d68226dda1cac2677f73c9fd9174fd13"); + yield return (Msg: "67f3f23df3bd8ebeb0096452fe4775fd9cc71fbb6e72fdcc7eb8094f42c903121d0817a927bcbabd3109d5a70420253deab2", MD: "f4207cc565f266a245f29bf20b95b5d9a83e1bb68ad988edc91faa25f25286c8398bac7dd6628259bff98f28360f263dfc54c4228bc437c5691de1219b758d9f"); + yield return (Msg: "a225070c2cb122c3354c74a254fc7b84061cba33005cab88c409fbd3738ff67ce23c41ebef46c7a61610f5b93fa92a5bda9569", MD: "e815a9a4e4887be014635e97958341e0519314b3a3289e1835121b153b462272b0aca418be96d60e5ab355d3eb463697c0191eb522b60b8463d89f4c3f1bf142"); + yield return (Msg: "6aa0886777e99c9acd5f1db6e12bda59a807f92411ae99c9d490b5656acb4b115c57beb3c1807a1b029ad64be1f03e15bafd91ec", MD: "241f2ebaf7ad09e173b184244e69acd7ebc94774d0fa3902cbf267d4806063b044131bcf4af4cf180eb7bd4e7960ce5fe3dc6aebfc6b90eec461f414f79a67d9"); + yield return (Msg: "6a06092a3cd221ae86b286b31f326248270472c5ea510cb9064d6024d10efee7f59e98785d4f09da554e97cdec7b75429d788c112f", MD: "d14a1a47f2bef9e0d4b3e90a6be9ab5893e1110b12db38d33ffb9a61e1661aecc4ea100839cfee58a1c5aff72915c14170dd99e13f71b0a5fc1985bf43415cb0"); + yield return (Msg: "dfc3fa61f7fffc7c88ed90e51dfc39a4f288b50d58ac83385b58a3b2a3a39d729862c40fcaf9bc308f713a43eecb0b72bb9458d204ba", MD: "947bc873dc41df195f8045deb6ea1b840f633917e79c70a88d38b8862197dc2ab0cc6314e974fb5ba7e1703b22b1309e37bd430879056bdc166573075a9c5e04"); + yield return (Msg: "52958b1ff0049efa5d050ab381ec99732e554dcd03725da991a37a80bd4756cf65d367c54721e93f1e0a22f70d36e9f841336956d3c523", MD: "9cc5aad0f529f4bac491d733537b69c8ec700fe38ab423d815e0927c8657f9cb8f4207762d816ab697580122066bc2b68f4177335d0a6e9081540779e572c41f"); + yield return (Msg: "302fa84fdaa82081b1192b847b81ddea10a9f05a0f04138fd1da84a39ba5e18e18bc3cea062e6df92ff1ace89b3c5f55043130108abf631e", MD: "8c8eaae9a445643a37df34cfa6a7f09deccab2a222c421d2fc574bbc5641e504354391e81eb5130280b1226812556d474e951bb78dbdd9b77d19f647e2e7d7be"); + yield return (Msg: "b82f500d6bc2dddcdc162d46cbfaa5ae64025d5c1cd72472dcd2c42161c9871ce329f94df445f0c8aceecafd0344f6317ecbb62f0ec2223a35", MD: "55c69d7accd179d5d9fcc522f794e7af5f0eec7198ffa39f80fb55b866c0857ff3e7aeef33e130d9c74ef90606ca821d20b7608b12e6e561f9e6c7122ace3db0"); + yield return (Msg: "86da9107ca3e16a2b58950e656a15c085b88033e79313e2c0f92f99f06fa187efba5b8fea08eb7145f8476304180dd280f36a072b7eac197f085", MD: "0d3b1a0459b4eca801e0737ff9ea4a12b9a483a73a8a92742a93c297b7149326bd92c1643c8177c8924482ab3bbd916c417580cc75d3d3ae096de531bc5dc355"); + yield return (Msg: "141a6eafe157053e780ac7a57b97990616ce1759ed132cb453bcdfcabdbb70b3767da4eb94125d9c2a8d6d20bfaeacc1ffbe49c4b1bb5da7e9b5c6", MD: "bdbdd5b94cdc89466e7670c63ba6a55b58294e93b351261a5457bf5a40f1b5b2e0acc7fceb1bfb4c8872777eeeaff7927fd3635ca18c996d870bf86b12b89ba5"); + yield return (Msg: "6e0c65ee0943e34d9bbd27a8547690f2291f5a86d713c2be258e6ac16919fe9c4d491895d3a961bb97f5fac255891a0eaa18f80e1fa1ebcb639fcfc1", MD: "39ebb992b8d39daae973e3813a50e9e79a67d8458a6f17f97a6dd30dd7d11d95701a11129ffeaf7d45781b21cac0c4c034e389d7590df5beeb9805072d0183b9"); + yield return (Msg: "57780b1c79e67fc3beaabead4a67a8cc98b83fa7647eae50c8798b96a516597b448851e93d1a62a098c4767333fcf7b463ce91edde2f3ad0d98f70716d", MD: "3ef36c3effad6eb5ad2d0a67780f80d1b90efcb74db20410c2261a3ab0f784429df874814748dc1b6efaab3d06dd0a41ba54fce59b67d45838eaa4aa1fadfa0f"); + yield return (Msg: "bcc9849da4091d0edfe908e7c3386b0cadadb2859829c9dfee3d8ecf9dec86196eb2ceb093c5551f7e9a4927faabcfaa7478f7c899cbef4727417738fc06", MD: "1fcd8a2c7b4fd98fcdc5fa665bab49bde3f9f556aa66b3646638f5a2d3806192f8a33145d8d0c535c85adff3cc0ea3c2715b33cec9f8886e9f4377b3632e9055"); + yield return (Msg: "05a32829642ed4808d6554d16b9b8023353ce65a935d126602970dba791623004dede90b52ac7f0d4335130a63cba68c656c139989614de20913e83db320db", MD: "49d8747bb53ddde6d1485965208670d1130bf35619d7506a2f2040d1129fcf0320207e5b36fea083e84ffc98755e691ad8bd5dc66f8972cb9857389344e11aad"); + yield return (Msg: "56ac4f6845a451dac3e8886f97f7024b64b1b1e9c5181c059b5755b9a6042be653a2a0d5d56a9e1e774be5c9312f48b4798019345beae2ffcc63554a3c69862e", MD: "5fde5c57a31febb98061f27e4506fa5c245506336ee90d595c91d791a5975c712b3ab9b3b5868f941db0aeb4c6d2837c4447442f8402e0e150a9dc0ef178dca8"); + yield return (Msg: "8a229f8d0294fe90d4cc8c875460d5d623f93287f905a999a2ab0f9a47046f78ef88b09445c671189c59388b3017cca2af8bdf59f8a6f04322b1701ec08624ab63", MD: "16b0fd239cc632842c443e1b92d286dd519cfc616a41f2456dd5cddebd10703c3e9cb669004b7f169bb4f99f350ec96904b0e8dd4de8e6be9953dc892c65099f"); + yield return (Msg: "87d6aa9979025b2437ea8159ea1d3e5d6f17f0a5b913b56970212f56de7884840c0da9a72865e1892aa780b8b8f5f57b46fc070b81ca5f00eee0470ace89b1e1466a", MD: "d816acf1797decfe34f4cc49e52aa505cc59bd17fe69dc9543fad82e9cf96298183021f704054d3d06adde2bf54e82a090a57b239e88daa04cb76c4fc9127843"); + yield return (Msg: "0823616ab87e4904308628c2226e721bb4169b7d34e8744a0700b721e38fe05e3f813fe4075d4c1a936d3a33da20cfb3e3ac722e7df7865330b8f62a73d9119a1f2199", MD: "e1da6be4403a4fd784c59be4e71c658a78bb8c5d7d571c5e816fbb3e218a4162f62de1c285f3779781cb5506e29c94e1b7c7d65af2aa71ea5c96d9585b5e45d5"); + yield return (Msg: "7d2d913c2460c09898b20366ae34775b1564f10edea49c073cebe41989bb93f38a533af1f425d3382f8aa40159b567358ee5a73b67df6d0dc09c1c92bf3f9a28124ab07f", MD: "3aa1e19a52b86cf414d977768bb535b7e5817117d436b4425ec8d775e8cb0e0b538072213884c7ff1bb9ca9984c82d65cb0115cc07332b0ea903e3b38650e88e"); + yield return (Msg: "fca5f68fd2d3a52187b349a8d2726b608fccea7db42e906b8718e85a0ec654fac70f5a839a8d3ff90cfed7aeb5ea9b08f487fc84e1d9f7fb831dea254468a65ba18cc5a126", MD: "2c74f846ecc722ea4a1eb1162e231b6903291fffa95dd5e1d17dbc2c2be7dfe549a80dd34487d714130ddc9924aed904ad55f49c91c80ceb05c0c034dae0a0a4"); + yield return (Msg: "881ff70ca34a3e1a0e864fd2615ca2a0e63def254e688c37a20ef6297cb3ae4c76d746b5e3d6bb41bd0d05d7df3eeded74351f4eb0ac801abe6dc10ef9b635055ee1dfbf4144", MD: "9a10a7ce23c0497fe8783927f833232ae664f1e1b91302266b6ace25a9c253d1ecab1aaaa62f865469480b2145ed0e489ae3f3f9f7e6da27492c81b07e606fb6"); + yield return (Msg: "b0de0430c200d74bf41ea0c92f8f28e11b68006a884e0d4b0d884533ee58b38a438cc1a75750b6434f467e2d0cd9aa4052ceb793291b93ef83fd5d8620456ce1aff2941b3605a4", MD: "9e9e469ca9226cd012f5c9cc39c96adc22f420030fcee305a0ed27974e3c802701603dac873ae4476e9c3d57e55524483fc01adaef87daa9e304078c59802757"); + yield return (Msg: "0ce9f8c3a990c268f34efd9befdb0f7c4ef8466cfdb01171f8de70dc5fefa92acbe93d29e2ac1a5c2979129f1ab08c0e77de7924ddf68a209cdfa0adc62f85c18637d9c6b33f4ff8", MD: "b018a20fcf831dde290e4fb18c56342efe138472cbe142da6b77eea4fce52588c04c808eb32912faa345245a850346faec46c3a16d39bd2e1ddb1816bc57d2da"); + + // First 5 from SHA3_512LongMsg.rsp + yield return ( + Msg: + "664ef2e3a7059daf1c58caf52008c5227e85cdcb83b4c59457f02c508d4f4f69f826bd82c0cffc5cb6a97af6e561c6f96970005285e58f21ef6511d26e709889a7e513c434c90a3c" + + "f7448f0caeec7114c747b2a0758a3b4503a7cf0c69873ed31d94dbef2b7b2f168830ef7da3322c3d3e10cafb7c2c33c83bbf4c46a31da90cff3bfd4ccc6ed4b310758491eeba603a" + + "76", + MD: "e5825ff1a3c070d5a52fbbe711854a440554295ffb7a7969a17908d10163bfbe8f1d52a676e8a0137b56a11cdf0ffbb456bc899fc727d14bd8882232549d914e"); + + yield return ( + Msg: + "991c4e7402c7da689dd5525af76fcc58fe9cc1451308c0c4600363586ccc83c9ec10a8c9ddaec3d7cfbd206484d09634b9780108440bf27a5fa4a428446b3214fa17084b6eb197c5" + + "c59a4e8df1cfc521826c3b1cbf6f4212f6bfb9bc106dfb5568395643de58bffa2774c31e67f5c1e7017f57caadbb1a56cc5b8a5cf9584552e17e7af9542ba13e9c54695e0dc8f24e" + + "ddb93d5a3678e10c8a80ff4f27b677d40bef5cb5f9b3a659cc4127970cd2c11ebf22d514812dfefdd73600dfc10efba38e93e5bff47736126043e50f8b9b941e4ec3083fb762dbf1" + + "5c86", + MD: "cd0f2a48e9aa8cc700d3f64efb013f3600ebdbb524930c682d21025eab990eb6d7c52e611f884031fafd9360e5225ab7e4ec24cbe97f3af6dbe4a86a4f068ba7"); + + yield return ( + Msg: + "22e1df25c30d6e7806cae35cd4317e5f94db028741a76838bfb7d5576fbccab001749a95897122c8d51bb49cfef854563e2b27d9013b28833f161d520856ca4b61c2641c4e184800" + + "300aede3518617c7be3a4e6655588f181e9641f8df7a6a42ead423003a8c4ae6be9d767af5623078bb116074638505c10540299219b0155f45b1c18a74548e4328de37a911140531" + + "deb6434c534af2449c1abe67e18030681a61240225f87ede15d519b7ce2500bccf33e1364e2fbe6a8a2fe6c15d73242610ed36b0740080812e8902ee531c88e0359020797cbdd1fb" + + "78848ae6b5105961d05cdddb8af5fef21b02db94c9810464b8d3ea5f047b94bf0d23931f12df37e102b603cd8e5f5ffa83488df257ddde110106262e0ef16d7ef213e7b49c69276d" + + "4d048f", + MD: "a6375ff04af0a18fb4c8175f671181b4cf79653a3d70847c6d99694b3f5d41601f1dbef809675c63cac4ec83153b1c78131a7b61024ce36244f320ab8740cb7e"); + + yield return ( + Msg: + "8237ce9396ccde3a616754414cdf7b5a958c1eb7f25a48c2781b4e0dba220f8c350d7b02ece252b94f5e2e766189c4ac1a8e67f00acacead402316196a9b0a673e24a33f18b7cb6b" + + "e4a066d33e1c93abd8252feb1c8d9cff134ac0c0861150a463264e316172d0b8e7d6043f2bbf71bf97fa7f9070ca3a21b93853ec55ab67a96db884c2113bea0822a70ea46f9ae550" + + "1eb55ec74eaa3179fa96d7842092d9e023844ed96f3c9fc35bbc8ee953d677c636fdd578fd5507719e0c55702fed2eaf4f32b35ec29a7a515bbc8bf61f9baf89a77aeb8bc6f24770" + + "6c41d398cae5ec80b76abc3a5380001aea500eb31b10160139d5a8e8f1a976dd2dde5ce439a29dba24d370536a14bb87cf201e088e5e3397b3b61477c6a41e22a98af53cc34bc8c5" + + "5f15d7924e7e32fed4d3c3ddc2ac8eb1dfc438218c08c6a6a8eea888b208f6092dd9f9df49e7ede8bf11051afd23b0b983a81bcc8d00f7d1f2b27cb04c03aeee59c7df23a17775ae" + + "5984eda7", + MD: "f08819ec3a9a9806a1f55be4f0e56bce084e66fa271784974bf80e1bed7b2be559ebf5b6396ce52f7db7ef45543965f83064095a70328489178718b491a4100d"); + + yield return ( + Msg: + "cfa6c0413dfc1a619417ac3f80fd38247b56941da8c2adf3ff70cc5dabed1875b0395d69d1200b73b1c7820b38868c5b38f52bf3514a96be12e27e34601d95d21c6f51c700b4edf1" + + "cac4b2079d487418a4cc5f34f815f469c4b44ef1a7dbaaa9597026c59260c9c22736c49d76ecf7430500b74866cbcfdb5e0fc4fa46cf5ee2b06363ca4ecba6d0104440348d191ec4" + + "a4bcbc9763152ffe271a69b805a0b9656970913dfd9e8c02cd16af33a878f083c926f48ab79b1db969fec493aef6c31accc1378867808440a5d5990490b07568bc66e9872904a0f4" + + "6ae25ef4077b85ea217bdd12541a9472e2a9840e0d6ab55cc4a523f782f8c19774efbd41dad506bbafc90c438c14c780cab9fab9e74eb9452a0b29438a21878bcd4c6be4edac4e77" + + "bfd14a83d6152253a62e826de503880d37bf82d10924fab6bd23f04308a9660499bb223afcc5afd1bd2fa592d0322a9a30eab90bc7ac22018e99d2c8f573554c85b019d0c4cd75e3" + + "59e5e9907082a8d660b353588b5f085486d89bd97bb32335cbd8b9adf7d57c72c078d9d08d9c09a70e43da1f1fe5b398ef08d2e06111d9a9b25a893a5d84cd643b0ffab8ef2755f7" + + "81c1d6ca49", + MD: "3a4c2c9284c90515cb34a0895d0374e87467ffbbc7c1dda3239893a12aeae3b9951169fe85605ef7aa2c483662f3a65c72ff12becde50c23ec6a2bc8864c27c1"); + } + } + } +} diff --git a/src/libraries/System.Security.Cryptography/tests/Sha512Tests.cs b/src/libraries/System.Security.Cryptography/tests/Sha512Tests.cs index 465f41c15fdf69..4360bf464dde28 100644 --- a/src/libraries/System.Security.Cryptography/tests/Sha512Tests.cs +++ b/src/libraries/System.Security.Cryptography/tests/Sha512Tests.cs @@ -8,8 +8,14 @@ namespace System.Security.Cryptography.Tests { - public class Sha512Tests : HashAlgorithmTestDriver + public class Sha512Tests : HashAlgorithmTestDriver { + public sealed class Traits : IHashTrait + { + public static bool IsSupported => true; + public static int HashSizeInBytes => SHA512.HashSizeInBytes; + } + protected override HashAlgorithm Create() { return SHA512.Create(); @@ -152,5 +158,12 @@ await VerifyRepeatingAsync( 1000000, "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973ebde0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"); } + + [Fact] + public void Sha512_HashSizes() + { + Assert.Equal(512, SHA512.HashSizeInBits); + Assert.Equal(64, SHA512.HashSizeInBytes); + } } } 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 eda1865b105c6e..d32b7c3f519491 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 @@ -262,6 +262,9 @@ + + + @@ -296,6 +299,9 @@ + + + diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertTests.cs index b83841fcab79d8..770379abec4204 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertTests.cs @@ -587,6 +587,20 @@ public static void CertificateWithTrailingDataCanBeRead() } } + [Fact] + public static void CertificateSha3Signed() + { + using (X509Certificate2 cert = new X509Certificate2(TestData.RsaSha3_256SignedCertificate)) + { + Assert.Equal("CN=potato", cert.Subject); + + using (RSA rsa = cert.PublicKey.GetRSAPublicKey()) + { + Assert.NotNull(rsa); + } + } + } + [ConditionalFact(typeof(PlatformSupport), nameof(PlatformSupport.PlatformCryptoProviderFunctional))] [OuterLoop("Hardware backed key generation takes several seconds.")] public static void CreateCertificate_MicrosoftPlatformCryptoProvider_EcdsaKey() diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/ECDsaX509SignatureGeneratorTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/ECDsaX509SignatureGeneratorTests.cs index c2b0b22b000b35..5c932f2dc45b1c 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/ECDsaX509SignatureGeneratorTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/ECDsaX509SignatureGeneratorTests.cs @@ -57,14 +57,11 @@ public static void PublicKeyEncoding(EccTestData testData) } [Theory] - [InlineData("SHA256")] - [InlineData("SHA384")] - [InlineData("SHA512")] - public static void SignatureAlgorithm_StableNotSame(string hashAlgorithmName) + [MemberData(nameof(SignatureDigestAlgorithms))] + public static void SignatureAlgorithm_StableNotSame(HashAlgorithmName hashAlgorithm) { using (ECDsa ecdsa = ECDsa.Create(EccTestData.Secp256r1Data.KeyParameters)) { - HashAlgorithmName hashAlgorithm = new HashAlgorithmName(hashAlgorithmName); var generator = X509SignatureGenerator.CreateForECDsa(ecdsa); byte[] sigAlg = generator.GetSignatureAlgorithmIdentifier(hashAlgorithm); @@ -93,18 +90,13 @@ public static void SignatureAlgorithm_NotSupported(string hashAlgorithmName) } [Theory] - [InlineData("SHA256")] - [InlineData("SHA384")] - [InlineData("SHA512")] - public static void SignatureAlgorithm_Encoding(string hashAlgorithmName) + [MemberData(nameof(SignatureDigestAlgorithms))] + public static void SignatureAlgorithm_Encoding(HashAlgorithmName hashAlgorithm) { string expectedAlgOid; - switch (hashAlgorithmName) + switch (hashAlgorithm.Name) { - case "SHA1": - expectedAlgOid = "06072A8648CE3D0401"; - break; case "SHA256": expectedAlgOid = "06082A8648CE3D040302"; break; @@ -114,8 +106,17 @@ public static void SignatureAlgorithm_Encoding(string hashAlgorithmName) case "SHA512": expectedAlgOid = "06082A8648CE3D040304"; break; + case "SHA3-256": + expectedAlgOid = "060960864801650304030A"; + break; + case "SHA3-384": + expectedAlgOid = "060960864801650304030B"; + break; + case "SHA3-512": + expectedAlgOid = "060960864801650304030C"; + break; default: - throw new ArgumentOutOfRangeException(nameof(hashAlgorithmName)); + throw new ArgumentOutOfRangeException(nameof(hashAlgorithm)); } EccTestData testData = EccTestData.Secp521r1Data; @@ -125,7 +126,7 @@ public static void SignatureAlgorithm_Encoding(string hashAlgorithmName) using (ECDsa ecdsa = ECDsa.Create(testData.KeyParameters)) { var generator = X509SignatureGenerator.CreateForECDsa(ecdsa); - byte[] sigAlg = generator.GetSignatureAlgorithmIdentifier(new HashAlgorithmName(hashAlgorithmName)); + byte[] sigAlg = generator.GetSignatureAlgorithmIdentifier(hashAlgorithm); Assert.Equal(expectedHex, sigAlg.ByteArrayToHex()); } @@ -135,5 +136,18 @@ public static IEnumerable GetApplicableTestData() { return EccTestData.EnumerateApplicableTests().Select(x => new object[] { x }); } + + public static IEnumerable SignatureDigestAlgorithms + { + get + { + yield return new object[] { HashAlgorithmName.SHA256 }; + yield return new object[] { HashAlgorithmName.SHA384 }; + yield return new object[] { HashAlgorithmName.SHA512 }; + yield return new object[] { HashAlgorithmName.SHA3_256 }; + yield return new object[] { HashAlgorithmName.SHA3_384 }; + yield return new object[] { HashAlgorithmName.SHA3_512 }; + } + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/RSAPkcs1X509SignatureGeneratorTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/RSAPkcs1X509SignatureGeneratorTests.cs index 0ded7c8c85950c..453892e6349ecf 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/RSAPkcs1X509SignatureGeneratorTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/RSAPkcs1X509SignatureGeneratorTests.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.Collections.Generic; using Test.Cryptography; using Xunit; @@ -57,10 +58,8 @@ public static void PublicKeyEncoding() } [Theory] - [InlineData("SHA256")] - [InlineData("SHA384")] - [InlineData("SHA512")] - public static void SignatureAlgorithm_StableNotSame(string hashAlgorithmName) + [MemberData(nameof(SignatureDigestAlgorithms))] + public static void SignatureAlgorithm_StableNotSame(HashAlgorithmName hashAlgorithm) { using (RSA rsa = RSA.Create()) { @@ -69,8 +68,6 @@ public static void SignatureAlgorithm_StableNotSame(string hashAlgorithmName) var signatureGenerator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); - HashAlgorithmName hashAlgorithm = new HashAlgorithmName(hashAlgorithmName); - byte[] sigAlg = signatureGenerator.GetSignatureAlgorithmIdentifier(hashAlgorithm); byte[] sigAlg2 = signatureGenerator.GetSignatureAlgorithmIdentifier(hashAlgorithm); @@ -101,14 +98,12 @@ public static void SignatureAlgorithm_NotSupported(string hashAlgorithmName) } [Theory] - [InlineData("SHA256")] - [InlineData("SHA384")] - [InlineData("SHA512")] - public static void SignatureAlgorithm_Encoding(string hashAlgorithmName) + [MemberData(nameof(SignatureDigestAlgorithms))] + public static void SignatureAlgorithm_Encoding(HashAlgorithmName hashAlgorithm) { string expectedOid; - switch (hashAlgorithmName) + switch (hashAlgorithm.Name) { case "MD5": expectedOid = "06092A864886F70D010104"; @@ -125,8 +120,17 @@ public static void SignatureAlgorithm_Encoding(string hashAlgorithmName) case "SHA512": expectedOid = "06092A864886F70D01010D"; break; + case "SHA3-256": + expectedOid = "060960864801650304030E"; + break; + case "SHA3-384": + expectedOid = "060960864801650304030F"; + break; + case "SHA3-512": + expectedOid = "0609608648016503040310"; + break; default: - throw new ArgumentOutOfRangeException(nameof(hashAlgorithmName)); + throw new ArgumentOutOfRangeException(nameof(hashAlgorithm)); } string expectedHex = $"30{(expectedOid.Length / 2 + 2):X2}{expectedOid}0500"; @@ -136,12 +140,24 @@ public static void SignatureAlgorithm_Encoding(string hashAlgorithmName) RSAParameters parameters = TestData.RsaBigExponentParams; rsa.ImportParameters(parameters); - HashAlgorithmName hashAlgorithm = new HashAlgorithmName(hashAlgorithmName); X509SignatureGenerator signatureGenerator = X509SignatureGenerator.CreateForRSA(rsa, RSASignaturePadding.Pkcs1); byte[] sigAlg = signatureGenerator.GetSignatureAlgorithmIdentifier(hashAlgorithm); Assert.Equal(expectedHex, sigAlg.ByteArrayToHex()); } } + + public static IEnumerable SignatureDigestAlgorithms + { + get + { + yield return new object[] { HashAlgorithmName.SHA256 }; + yield return new object[] { HashAlgorithmName.SHA384 }; + yield return new object[] { HashAlgorithmName.SHA512 }; + yield return new object[] { HashAlgorithmName.SHA3_256 }; + yield return new object[] { HashAlgorithmName.SHA3_384 }; + yield return new object[] { HashAlgorithmName.SHA3_512 }; + } + } } } diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/RSAPssX509SignatureGeneratorTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/RSAPssX509SignatureGeneratorTests.cs index ef89a1da872d41..216bb1ca84cbec 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/RSAPssX509SignatureGeneratorTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/CertificateCreation/RSAPssX509SignatureGeneratorTests.cs @@ -83,6 +83,9 @@ public static void SignatureAlgorithm_StableNotSame(string hashAlgorithmName) [InlineData("MD5")] [InlineData("SHA1")] [InlineData("Potato")] + [InlineData("SHA3-256")] // There are no OIDs assigned for RSA-PSS-withSHA3 family. + [InlineData("SHA3-384")] + [InlineData("SHA3-512")] public static void SignatureAlgorithm_NotSupported(string hashAlgorithmName) { using (RSA rsa = RSA.Create()) diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.cs index 93b24685c937c7..23bef2b46c250a 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/ChainTests.cs @@ -1253,6 +1253,22 @@ public static void BuildChainForCertificateWithMD5Signature() } } + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.SupportsSha3))] + [SkipOnPlatform(~TestPlatforms.Linux, "Only Linux SHA3 supports chain building.")] + public static void BuildChainForSelfSignedSha3Certificate() + { + using (ChainHolder chainHolder = new ChainHolder()) + using (X509Certificate2 cert = new X509Certificate2(TestData.RsaSha3_256SignedCertificate)) + { + X509Chain chain = chainHolder.Chain; + chain.ChainPolicy.RevocationMode = X509RevocationMode.NoCheck; + chain.ChainPolicy.VerificationTime = cert.NotBefore.AddHours(2); + chain.ChainPolicy.TrustMode = X509ChainTrustMode.CustomRootTrust; + chain.ChainPolicy.CustomTrustStore.Add(cert); + Assert.True(chain.Build(cert), AllStatusFlags(chain).ToString()); + } + } + internal static X509ChainStatusFlags AllStatusFlags(this X509Chain chain) { return chain.ChainStatus.Aggregate( diff --git a/src/libraries/System.Security.Cryptography/tests/X509Certificates/TestData.cs b/src/libraries/System.Security.Cryptography/tests/X509Certificates/TestData.cs index 92d8606e3093b4..64c8d7e3a11062 100644 --- a/src/libraries/System.Security.Cryptography/tests/X509Certificates/TestData.cs +++ b/src/libraries/System.Security.Cryptography/tests/X509Certificates/TestData.cs @@ -2511,6 +2511,34 @@ internal struct ECDsaCngKeyValues "153ac22391a1603547ffb3f9b328c59e59b5d64568b9c451df233fe9a581116f" + "05be8c67b92bc7df9984f30535ad53817cb4abcd77cb521856").HexToByteArray(); + internal static byte[] RsaSha3_256SignedCertificate =( + "30820303308201eba00302010202147bcedeaa2286e1308106525ad7efbe" + + "fb88e96995300d060960864801650304030e05003011310f300d06035504" + + "030c06706f7461746f301e170d3233303531383138303135305a170d3233" + + "303631373138303135305a3011310f300d06035504030c06706f7461746f" + + "30820122300d06092a864886f70d01010105000382010f003082010a0282" + + "010100ef7fd4e037107937b690472066d58048580cfa3822dfb91b776e76" + + "dc1de93b7f72d613d836c423909f139f909f7e5b77c610c114f2accee09f" + + "ee9f431524480f31e246c42e31807cdd3cc831f3ef6b601df4f81ecfede1" + + "96f90f9ea25749a9cb7af32bdc4857a9f272a87acd5ca73b288ed8817f71" + + "6c1297166c76b097be22f4705f0678ce3057b05580418649b381a7bcb44f" + + "9cfd429cc788487d3632de477c1ac6d430d8beeeee258e094388b8b3a9c2" + + "7a4b48f2d049beb56de950585f3c6c6308321e53cb37894c1b2a0b55a731" + + "e7861f6342f3f451ea0977dd4ef65f95b3218702722df9aa3672888ee040" + + "5eb4f4969e416150fa5460637f0071d7e444190203010001a3533051301d" + + "0603551d0e04160414ab91d8c96f342fb48b7903361835b1a4e255534d30" + + "1f0603551d23041830168014ab91d8c96f342fb48b7903361835b1a4e255" + + "534d300f0603551d130101ff040530030101ff300d060960864801650304" + + "030e05000382010100bf3f9103c076fc81d3d0d7b770280d2cbe56eb568b" + + "24a4ea526eaec44408f3d6581968c45f20dc62c24da618b8453dd6874314" + + "82de6cb7e66826edc8daf10cb5273ae1fda4b290b6b0fa46431fdb92a03a" + + "71a0174d1f780f3de4b2d2a8067e230e77e8e8b8bc88a6e43f1fdfcd2280" + + "16de21af0a2e46f3401c5a598adc1532041b2b211087358fb15e71becd53" + + "43c6fe33b374cef8030556a42a97fdf7a1387cbbeaa4ee74a5525321355c" + + "d06582c8be0bc642e98e36fc94019b83e1fa3827db6b914e3cefb1127c89" + + "4160a40665fc6663e70f42c25de76dcdd8c6ad96deb53560e870ab826a86" + + "ad82f8f331c63b3b5f256af0b702cf2413f6a1dc37a57d1d69").HexToByteArray(); + internal static byte[] ConcatenatedPemFile = ByteUtils.AsciiBytes( @"-----BEGIN CERTIFICATE----- MIIFcDCCBFigAwIBAgIQB6krbZc11OZ5l2/FnU3CpTANBgkqhkiG9w0BAQsFADBG diff --git a/src/libraries/System.Security.Permissions/src/CompatibilitySuppressions.xml b/src/libraries/System.Security.Permissions/src/CompatibilitySuppressions.xml index 8559c96ac0ee39..10869bf91f9227 100644 --- a/src/libraries/System.Security.Permissions/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Security.Permissions/src/CompatibilitySuppressions.xml @@ -49,6 +49,224 @@ lib/netstandard2.0/System.Security.Permissions.dll lib/net6.0/System.Security.Permissions.dll + + + CP0014 + F:System.Security.Permissions.ReflectionPermissionFlag.AllFlags:[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + F:System.Security.Permissions.ReflectionPermissionFlag.ReflectionEmit:[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + F:System.Security.Permissions.ReflectionPermissionFlag.TypeInformation:[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.CodeAccessPermission.Deny:[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.CodeAccessPermission.RevertDeny:[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.HostSecurityManager.ResolvePolicy(System.Security.Policy.Evidence):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.PermissionSet.ConvertPermissionSet(System.String,System.Byte[],System.String):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.PermissionSet.Deny:[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.Policy.PolicyLevel.AddFullTrustAssembly(System.Security.Policy.StrongName):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.Policy.PolicyLevel.AddFullTrustAssembly(System.Security.Policy.StrongNameMembershipCondition):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.Policy.PolicyLevel.CreateAppDomainLevel:[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.Policy.PolicyLevel.RemoveFullTrustAssembly(System.Security.Policy.StrongName):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.Policy.PolicyLevel.RemoveFullTrustAssembly(System.Security.Policy.StrongNameMembershipCondition):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.SecurityManager.IsGranted(System.Security.IPermission):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.SecurityManager.LoadPolicyLevelFromFile(System.String,System.Security.PolicyLevelType):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.SecurityManager.LoadPolicyLevelFromString(System.String,System.Security.PolicyLevelType):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.SecurityManager.PolicyHierarchy:[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.SecurityManager.ResolvePolicy(System.Security.Policy.Evidence,System.Security.PermissionSet,System.Security.PermissionSet,System.Security.PermissionSet,System.Security.PermissionSet@):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.SecurityManager.ResolvePolicy(System.Security.Policy.Evidence):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.SecurityManager.ResolvePolicy(System.Security.Policy.Evidence[]):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.SecurityManager.ResolvePolicyGroups(System.Security.Policy.Evidence):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.SecurityManager.ResolveSystemPolicy(System.Security.Policy.Evidence):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.SecurityManager.SavePolicy:[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + M:System.Security.SecurityManager.SavePolicyLevel(System.Security.Policy.PolicyLevel):[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + P:System.Security.Permissions.RegistryPermissionAttribute.All:[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + P:System.Security.Policy.PolicyLevel.FullTrustAssemblies:[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + P:System.Security.SecurityManager.CheckExecutionRights:[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + P:System.Security.SecurityManager.SecurityEnabled:[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + T:System.Security.Policy.FirstMatchCodeGroup:[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + T:System.Security.Policy.PermissionRequestEvidence:[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + + + CP0014 + T:System.Security.Policy.UnionCodeGroup:[T:System.ObsoleteAttribute] + lib/netstandard2.0/System.Security.Permissions.dll + lib/netstandard2.0/System.Security.Permissions.dll + true + CP0015 M:System.Security.Policy.Evidence.#ctor(System.Object[],System.Object[]):[T:System.ObsoleteAttribute] @@ -361,4 +579,4 @@ lib/netstandard2.0/System.Security.Permissions.dll lib/net462/System.Security.Permissions.dll - \ No newline at end of file + diff --git a/src/libraries/System.Speech/src/Internal/ObjectToken/RegistryDataKey.cs b/src/libraries/System.Speech/src/Internal/ObjectToken/RegistryDataKey.cs index fba6ad398d7e31..1acdb786aaca1f 100644 --- a/src/libraries/System.Speech/src/Internal/ObjectToken/RegistryDataKey.cs +++ b/src/libraries/System.Speech/src/Internal/ObjectToken/RegistryDataKey.cs @@ -64,7 +64,7 @@ internal static RegistryDataKey Open(string registryPath, bool fCreateIfNotExist } // If the last character is a '\', get rid of it - registryPath = registryPath.Trim(new char[] { '\\' }); + registryPath = registryPath.Trim('\\'); string rootPath = GetFirstKeyAndParseRemainder(ref registryPath); diff --git a/src/libraries/System.Speech/src/Internal/SrgsCompiler/AppDomainGrammarProxy.cs b/src/libraries/System.Speech/src/Internal/SrgsCompiler/AppDomainGrammarProxy.cs index c514d9aa7040f9..8a3ba87c938490 100644 --- a/src/libraries/System.Speech/src/Internal/SrgsCompiler/AppDomainGrammarProxy.cs +++ b/src/libraries/System.Speech/src/Internal/SrgsCompiler/AppDomainGrammarProxy.cs @@ -277,7 +277,7 @@ private static string FormatConstructorParameters(MethodInfo[] cis, string metho ///
private static NameValuePair[] ParseInitParams(string initParameters) { - string[] parameters = initParameters.Split(new char[] { ';' }, StringSplitOptions.None); + string[] parameters = initParameters.Split(';', StringSplitOptions.None); NameValuePair[] pairs = new NameValuePair[parameters.Length]; for (int i = 0; i < parameters.Length; i++) diff --git a/src/libraries/System.Speech/src/Recognition/Grammar.cs b/src/libraries/System.Speech/src/Recognition/Grammar.cs index d7f19a4262dd5a..39f79ba4229776 100644 --- a/src/libraries/System.Speech/src/Recognition/Grammar.cs +++ b/src/libraries/System.Speech/src/Recognition/Grammar.cs @@ -850,7 +850,7 @@ private static NameValuePair[] ParseInitParams(string initParameters) return Array.Empty(); } - string[] parameters = initParameters.Split(new char[] { ';' }, StringSplitOptions.None); + string[] parameters = initParameters.Split(';', StringSplitOptions.None); NameValuePair[] pairs = new NameValuePair[parameters.Length]; for (int i = 0; i < parameters.Length; i++) diff --git a/src/libraries/System.Speech/src/Recognition/RecognizerBase.cs b/src/libraries/System.Speech/src/Recognition/RecognizerBase.cs index dc617c14f15ae8..29be40695d2d70 100644 --- a/src/libraries/System.Speech/src/Recognition/RecognizerBase.cs +++ b/src/libraries/System.Speech/src/Recognition/RecognizerBase.cs @@ -1404,7 +1404,7 @@ private void LoadSapiGrammar(Grammar grammar, SapiGrammar sapiGrammar, bool enab { // If the base Uri has not been set any other way, then set the base Uri for this file string uri = grammar.Uri.OriginalString; - int posSlash = uri.LastIndexOfAny(new char[] { '\\', '/' }); + int posSlash = uri.LastIndexOfAny(s_slashes); if (posSlash >= 0) { baseUri = new Uri(uri.Substring(0, posSlash + 1), UriKind.RelativeOrAbsolute); @@ -1489,7 +1489,7 @@ int ISpGrammarResourceLoader.LoadResource(string bstrResourceUri, bool fAlwaysRe string ruleName = pbstrMIMEType; // The parent is the first - string[] ids = pbstrRedirectUrl.Split(new char[] { ' ' }, StringSplitOptions.None); + string[] ids = pbstrRedirectUrl.Split(' ', StringSplitOptions.None); System.Diagnostics.Debug.Assert(ids.Length == 2); uint parentGrammarId = uint.Parse(ids[0], CultureInfo.InvariantCulture); @@ -3044,6 +3044,7 @@ private static void CheckGrammarOptionsOnSapi51(Grammar grammar) private TimeSpan _defaultTimeout = TimeSpan.FromSeconds(30); private RecognizerBaseThunk _recoThunk; + private static readonly char[] s_slashes = new char[] { '\\', '/' }; #endregion private sealed class RecognizerBaseThunk : ISpGrammarResourceLoader diff --git a/src/libraries/System.Text.Json/gen/Helpers/KnownTypeSymbols.cs b/src/libraries/System.Text.Json/gen/Helpers/KnownTypeSymbols.cs index 2c32d002381afa..73d5bbd324ca65 100644 --- a/src/libraries/System.Text.Json/gen/Helpers/KnownTypeSymbols.cs +++ b/src/libraries/System.Text.Json/gen/Helpers/KnownTypeSymbols.cs @@ -197,6 +197,9 @@ public KnownTypeSymbols(Compilation compilation) public INamedTypeSymbol? JsonUnmappedMemberHandlingAttributeType => GetOrResolveType("System.Text.Json.Serialization.JsonUnmappedMemberHandlingAttribute", ref _JsonUnmappedMemberHandlingAttributeType); private Option _JsonUnmappedMemberHandlingAttributeType; + public INamedTypeSymbol? JsonStringEnumConverterType => GetOrResolveType("System.Text.Json.Serialization.JsonStringEnumConverter", ref _JsonStringEnumConverterType); + private Option _JsonStringEnumConverterType; + // Unsupported types public INamedTypeSymbol? DelegateType => _DelegateType ??= Compilation.GetSpecialType(SpecialType.System_Delegate); private INamedTypeSymbol? _DelegateType; @@ -213,6 +216,11 @@ public KnownTypeSymbols(Compilation compilation) public INamedTypeSymbol? UIntPtrType => GetOrResolveType(typeof(UIntPtr), ref _UIntPtrType); private Option _UIntPtrType; + public INamedTypeSymbol? MemoryType => GetOrResolveType(typeof(Memory<>), ref _MemoryType); + private Option _MemoryType; + + public INamedTypeSymbol? ReadOnlyMemoryType => GetOrResolveType(typeof(ReadOnlyMemory<>), ref _ReadOnlyMemoryType); + private Option _ReadOnlyMemoryType; public bool IsImmutableEnumerableType(ITypeSymbol type, out string? factoryTypeFullName) { diff --git a/src/libraries/System.Text.Json/gen/Helpers/RoslynExtensions.cs b/src/libraries/System.Text.Json/gen/Helpers/RoslynExtensions.cs index 34b981448446d7..6497556d8c2510 100644 --- a/src/libraries/System.Text.Json/gen/Helpers/RoslynExtensions.cs +++ b/src/libraries/System.Text.Json/gen/Helpers/RoslynExtensions.cs @@ -104,12 +104,6 @@ public static bool ContainsAttribute(this ISymbol memberInfo, string attributeFu public static bool IsVirtual(this ISymbol symbol) => symbol.IsVirtual || symbol.IsOverride || symbol.IsAbstract; - public static bool IsNestedPrivate(this ISymbol symbol) - => symbol.DeclaredAccessibility is Accessibility.Private && symbol.ContainingType != null; - - public static bool IsPublic(this ITypeSymbol symbol) - => symbol.DeclaredAccessibility is Accessibility.Public && symbol.ContainingType is null; - public static bool IsAssignableFrom(this ITypeSymbol? baseType, ITypeSymbol? type) { if (baseType is null || type is null) diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.DiagnosticDescriptors.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.DiagnosticDescriptors.cs index 17d7dd58dbe416..bd0128b36dceb7 100644 --- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.DiagnosticDescriptors.cs +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.DiagnosticDescriptors.cs @@ -72,6 +72,14 @@ internal static class DiagnosticDescriptors category: JsonConstants.SystemTextJsonSourceGenerationName, defaultSeverity: DiagnosticSeverity.Warning, isEnabledByDefault: true); + + public static DiagnosticDescriptor JsonStringEnumConverterNotSupportedInAot { get; } = new DiagnosticDescriptor( + id: "SYSLIB1040", + title: new LocalizableResourceString(nameof(SR.JsonStringEnumConverterNotSupportedTitle), SR.ResourceManager, typeof(FxResources.System.Text.Json.SourceGeneration.SR)), + messageFormat: new LocalizableResourceString(nameof(SR.JsonStringEnumConverterNotSupportedMessageFormat), SR.ResourceManager, typeof(FxResources.System.Text.Json.SourceGeneration.SR)), + category: JsonConstants.SystemTextJsonSourceGenerationName, + defaultSeverity: DiagnosticSeverity.Warning, + isEnabledByDefault: true); } } } diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs index e329d014f075c3..ef46c4034b365e 100644 --- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Emitter.cs @@ -33,6 +33,7 @@ private sealed partial class Emitter private const string PropInitMethodNameSuffix = "PropInit"; private const string TryGetTypeInfoForRuntimeCustomConverterMethodName = "TryGetTypeInfoForRuntimeCustomConverter"; private const string ExpandConverterMethodName = "ExpandConverter"; + private const string GetConverterForNullablePropertyMethodName = "GetConverterForNullableProperty"; private const string SerializeHandlerPropName = "SerializeHandler"; private const string OptionsLocalVariableName = "options"; private const string ValueVarName = "value"; @@ -79,6 +80,11 @@ private sealed partial class Emitter ///
private readonly Dictionary _propertyNames = new(); + /// + /// Indicates that the type graph contains a nullable property with a design-time custom converter declaration. + /// + private bool _emitGetConverterForNullablePropertyMethod; + /// /// The SourceText emit implementation filled by the individual Roslyn versions. /// @@ -88,6 +94,7 @@ public void Emit(ContextGenerationSpec contextGenerationSpec) { Debug.Assert(_typeIndex.Count == 0); Debug.Assert(_propertyNames.Count == 0); + Debug.Assert(!_emitGetConverterForNullablePropertyMethod); foreach (TypeGenerationSpec spec in contextGenerationSpec.GeneratedTypes) { @@ -106,7 +113,7 @@ public void Emit(ContextGenerationSpec contextGenerationSpec) string contextName = contextGenerationSpec.ContextType.Name; // Add root context implementation. - AddSource($"{contextName}.g.cs", GetRootJsonContextImplementation(contextGenerationSpec)); + AddSource($"{contextName}.g.cs", GetRootJsonContextImplementation(contextGenerationSpec, _emitGetConverterForNullablePropertyMethod)); // Add GetJsonTypeInfo override implementation. AddSource($"{contextName}.GetJsonTypeInfo.g.cs", GetGetTypeInfoImplementation(contextGenerationSpec)); @@ -114,6 +121,7 @@ public void Emit(ContextGenerationSpec contextGenerationSpec) // Add property name initialization. AddSource($"{contextName}.PropertyNames.g.cs", GetPropertyNameInitialization(contextGenerationSpec)); + _emitGetConverterForNullablePropertyMethod = false; _propertyNames.Clear(); _typeIndex.Clear(); } @@ -217,8 +225,13 @@ private static SourceText GenerateForTypeWithBuiltInConverter(ContextGenerationS string typeFQN = typeMetadata.TypeRef.FullyQualifiedName; string typeInfoPropertyName = typeMetadata.TypeInfoPropertyName; - string metadataInitSource = $"{JsonTypeInfoReturnValueLocalVariableName} = {JsonMetadataServicesTypeRef}.{GetCreateValueInfoMethodRef(typeFQN)}({OptionsLocalVariableName}, {JsonMetadataServicesTypeRef}.{typeInfoPropertyName}Converter);"; - GenerateTypeInfoProperty(writer, typeMetadata, metadataInitSource); + + GenerateTypeInfoFactoryHeader(writer, typeMetadata); + writer.WriteLine($""" + {JsonTypeInfoReturnValueLocalVariableName} = {JsonMetadataServicesTypeRef}.{GetCreateValueInfoMethodRef(typeFQN)}({OptionsLocalVariableName}, {JsonMetadataServicesTypeRef}.{typeInfoPropertyName}Converter); + """); + + GenerateTypeInfoFactoryFooter(writer); return CompleteSourceFileAndReturnText(writer); } @@ -230,12 +243,16 @@ private static SourceText GenerateForTypeWithCustomConverter(ContextGenerationSp SourceWriter writer = CreateSourceWriterWithContextHeader(contextSpec); string typeFQN = typeMetadata.TypeRef.FullyQualifiedName; - string metadataInitSource = $$""" - {{JsonConverterTypeRef}} converter = {{ExpandConverterMethodName}}(typeof({{typeFQN}}), new {{typeMetadata.ConverterType.FullyQualifiedName}}(), {{OptionsLocalVariableName}}); - {{JsonTypeInfoReturnValueLocalVariableName}} = {{JsonMetadataServicesTypeRef}}.{{GetCreateValueInfoMethodRef(typeFQN)}} ({{OptionsLocalVariableName}}, converter); - """; + string converterFQN = typeMetadata.ConverterType.FullyQualifiedName; - GenerateTypeInfoProperty(writer, typeMetadata, metadataInitSource); + GenerateTypeInfoFactoryHeader(writer, typeMetadata); + + writer.WriteLine($""" + {JsonConverterTypeRef} converter = {ExpandConverterMethodName}(typeof({typeFQN}), new {converterFQN}(), {OptionsLocalVariableName}); + {JsonTypeInfoReturnValueLocalVariableName} = {JsonMetadataServicesTypeRef}.{GetCreateValueInfoMethodRef(typeFQN)} ({OptionsLocalVariableName}, converter); + """); + + GenerateTypeInfoFactoryFooter(writer); return CompleteSourceFileAndReturnText(writer); } @@ -249,13 +266,14 @@ private static SourceText GenerateForNullable(ContextGenerationSpec contextSpec, string typeFQN = typeMetadata.TypeRef.FullyQualifiedName; string underlyingTypeFQN = typeMetadata.NullableUnderlyingType.FullyQualifiedName; - string metadataInitSource = $$""" - {{JsonTypeInfoReturnValueLocalVariableName}} = {{JsonMetadataServicesTypeRef}}.{{GetCreateValueInfoMethodRef(typeFQN)}}( - {{OptionsLocalVariableName}}, - {{JsonMetadataServicesTypeRef}}.GetNullableConverter<{{underlyingTypeFQN}}>({{OptionsLocalVariableName}})); - """; + GenerateTypeInfoFactoryHeader(writer, typeMetadata); + + writer.WriteLine($$""" + {{JsonConverterTypeRef}} converter = {{JsonMetadataServicesTypeRef}}.GetNullableConverter<{{underlyingTypeFQN}}>({{OptionsLocalVariableName}}); + {{JsonTypeInfoReturnValueLocalVariableName}} = {{JsonMetadataServicesTypeRef}}.{{GetCreateValueInfoMethodRef(typeFQN)}}({{OptionsLocalVariableName}}, converter); + """); - GenerateTypeInfoProperty(writer, typeMetadata, metadataInitSource); + GenerateTypeInfoFactoryFooter(writer); return CompleteSourceFileAndReturnText(writer); } @@ -265,9 +283,13 @@ private static SourceText GenerateForUnsupportedType(ContextGenerationSpec conte SourceWriter writer = CreateSourceWriterWithContextHeader(contextSpec); string typeFQN = typeMetadata.TypeRef.FullyQualifiedName; - string metadataInitSource = $"{JsonTypeInfoReturnValueLocalVariableName} = {JsonMetadataServicesTypeRef}.{GetCreateValueInfoMethodRef(typeFQN)}({OptionsLocalVariableName}, {JsonMetadataServicesTypeRef}.GetUnsupportedTypeConverter<{typeFQN}>());"; - GenerateTypeInfoProperty(writer, typeMetadata, metadataInitSource); + GenerateTypeInfoFactoryHeader(writer, typeMetadata); + writer.WriteLine($""" + {JsonTypeInfoReturnValueLocalVariableName} = {JsonMetadataServicesTypeRef}.{GetCreateValueInfoMethodRef(typeFQN)}({OptionsLocalVariableName}, {JsonMetadataServicesTypeRef}.GetUnsupportedTypeConverter<{typeFQN}>()); + """); + + GenerateTypeInfoFactoryFooter(writer); return CompleteSourceFileAndReturnText(writer); } @@ -277,8 +299,13 @@ private static SourceText GenerateForEnum(ContextGenerationSpec contextSpec, Typ SourceWriter writer = CreateSourceWriterWithContextHeader(contextSpec); string typeFQN = typeMetadata.TypeRef.FullyQualifiedName; - string metadataInitSource = $"{JsonTypeInfoReturnValueLocalVariableName} = {JsonMetadataServicesTypeRef}.{GetCreateValueInfoMethodRef(typeFQN)}({OptionsLocalVariableName}, {JsonMetadataServicesTypeRef}.GetEnumConverter<{typeFQN}>({OptionsLocalVariableName}));"; - GenerateTypeInfoProperty(writer, typeMetadata, metadataInitSource); + + GenerateTypeInfoFactoryHeader(writer, typeMetadata); + writer.WriteLine($""" + {JsonTypeInfoReturnValueLocalVariableName} = {JsonMetadataServicesTypeRef}.{GetCreateValueInfoMethodRef(typeFQN)}({OptionsLocalVariableName}, {JsonMetadataServicesTypeRef}.GetEnumConverter<{typeFQN}>({OptionsLocalVariableName})); + """); + + GenerateTypeInfoFactoryFooter(writer); return CompleteSourceFileAndReturnText(writer); } @@ -341,8 +368,10 @@ private SourceText GenerateForCollection(ContextGenerationSpec contextSpec, Type break; } - string metadataInitSource = $$""" - var {{InfoVarName}} = new {{JsonCollectionInfoValuesTypeRef}}<{{typeFQN}}>() + GenerateTypeInfoFactoryHeader(writer, typeGenerationSpec); + + writer.WriteLine($$""" + var {{InfoVarName}} = new {{JsonCollectionInfoValuesTypeRef}}<{{typeFQN}}> { {{ObjectCreatorPropName}} = {{FormatDefaultConstructorExpr(typeGenerationSpec)}}, {{NumberHandlingPropName}} = {{GetNumberHandlingAsStr(typeGenerationSpec.NumberHandling)}}, @@ -350,9 +379,9 @@ private SourceText GenerateForCollection(ContextGenerationSpec contextSpec, Type }; {{JsonTypeInfoReturnValueLocalVariableName}} = {{JsonMetadataServicesTypeRef}}.{{createCollectionMethodExpr}}; - """; + """); - GenerateTypeInfoProperty(writer, typeGenerationSpec, metadataInitSource); + GenerateTypeInfoFactoryFooter(writer); if (serializeMethodName != null) { @@ -483,8 +512,10 @@ private SourceText GenerateForObject(ContextGenerationSpec contextSpec, TypeGene const string ObjectInfoVarName = "objectInfo"; string genericArg = typeMetadata.TypeRef.FullyQualifiedName; - string metadataInitSource = $$""" - var {{ObjectInfoVarName}} = new {{JsonObjectInfoValuesTypeRef}}<{{genericArg}}>() + GenerateTypeInfoFactoryHeader(writer, typeMetadata); + + writer.WriteLine($$""" + var {{ObjectInfoVarName}} = new {{JsonObjectInfoValuesTypeRef}}<{{genericArg}}> { {{ObjectCreatorPropName}} = {{creatorInvocation}}, ObjectWithParameterizedConstructorCreator = {{parameterizedCreatorInvocation}}, @@ -495,25 +526,24 @@ private SourceText GenerateForObject(ContextGenerationSpec contextSpec, TypeGene }; {{JsonTypeInfoReturnValueLocalVariableName}} = {{JsonMetadataServicesTypeRef}}.CreateObjectInfo<{{typeMetadata.TypeRef.FullyQualifiedName}}>({{OptionsLocalVariableName}}, {{ObjectInfoVarName}}); - """; + """); - if (typeMetadata.UnmappedMemberHandling != null) + if (typeMetadata is { UnmappedMemberHandling: not null } or { PreferredPropertyObjectCreationHandling: not null }) { - metadataInitSource += $""" - - {JsonTypeInfoReturnValueLocalVariableName}.{UnmappedMemberHandlingPropName} = {GetUnmappedMemberHandlingAsStr(typeMetadata.UnmappedMemberHandling.Value)}; - """; - } + writer.WriteLine(); - if (typeMetadata.PreferredPropertyObjectCreationHandling != null) - { - metadataInitSource += $""" + if (typeMetadata.UnmappedMemberHandling != null) + { + writer.WriteLine($"{JsonTypeInfoReturnValueLocalVariableName}.{UnmappedMemberHandlingPropName} = {GetUnmappedMemberHandlingAsStr(typeMetadata.UnmappedMemberHandling.Value)};"); + } - {JsonTypeInfoReturnValueLocalVariableName}.{PreferredPropertyObjectCreationHandlingPropName} = {GetObjectCreationHandlingAsStr(typeMetadata.PreferredPropertyObjectCreationHandling.Value)}; - """; + if (typeMetadata.PreferredPropertyObjectCreationHandling != null) + { + writer.WriteLine($"{JsonTypeInfoReturnValueLocalVariableName}.{PreferredPropertyObjectCreationHandlingPropName} = {GetObjectCreationHandlingAsStr(typeMetadata.PreferredPropertyObjectCreationHandling.Value)};"); + } } - GenerateTypeInfoProperty(writer, typeMetadata, metadataInitSource); + GenerateTypeInfoFactoryFooter(writer); if (propInitMethodName != null) { @@ -539,7 +569,7 @@ private SourceText GenerateForObject(ContextGenerationSpec contextSpec, TypeGene return CompleteSourceFileAndReturnText(writer); } - private static void GeneratePropMetadataInitFunc(SourceWriter writer, string propInitMethodName, TypeGenerationSpec typeGenerationSpec) + private void GeneratePropMetadataInitFunc(SourceWriter writer, string propInitMethodName, TypeGenerationSpec typeGenerationSpec) { Debug.Assert(typeGenerationSpec.PropertyGenSpecs != null); ImmutableEquatableArray properties = typeGenerationSpec.PropertyGenSpecs; @@ -561,9 +591,9 @@ private static void GeneratePropMetadataInitFunc(SourceWriter writer, string pro string getterValue = property switch { { DefaultIgnoreCondition: JsonIgnoreCondition.Always } => "null", - { CanUseGetter: true } => $"static (obj) => (({declaringTypeFQN})obj).{propertyName}", + { CanUseGetter: true } => $"static obj => (({declaringTypeFQN})obj).{propertyName}", { CanUseGetter: false, HasJsonInclude: true } - => $"""static (obj) => throw new {InvalidOperationExceptionTypeRef}("{string.Format(ExceptionMessages.InaccessibleJsonIncludePropertiesNotSupported, typeGenerationSpec.TypeRef.Name, propertyName)}")""", + => $"""static _ => throw new {InvalidOperationExceptionTypeRef}("{string.Format(ExceptionMessages.InaccessibleJsonIncludePropertiesNotSupported, typeGenerationSpec.TypeRef.Name, propertyName)}")""", _ => "null" }; @@ -585,18 +615,26 @@ private static void GeneratePropMetadataInitFunc(SourceWriter writer, string pro ? $"{JsonIgnoreConditionTypeRef}.{property.DefaultIgnoreCondition.Value}" : "null"; - string converterInstantiationExpr = property.ConverterType != null - ? $"({JsonConverterTypeRef}<{propertyTypeFQN}>){ExpandConverterMethodName}(typeof({propertyTypeFQN}), new {property.ConverterType.FullyQualifiedName}(), {OptionsLocalVariableName})" - : "null"; + string? converterInstantiationExpr = null; + if (property.ConverterType != null) + { + string converterFQN = property.ConverterType.FullyQualifiedName; + TypeRef? nullableUnderlyingType = _typeIndex[property.PropertyType].NullableUnderlyingType; + _emitGetConverterForNullablePropertyMethod |= nullableUnderlyingType != null; + + converterInstantiationExpr = nullableUnderlyingType != null + ? $"{GetConverterForNullablePropertyMethodName}<{nullableUnderlyingType.FullyQualifiedName}>(new {converterFQN}(), {OptionsLocalVariableName})" + : $"({JsonConverterTypeRef}<{propertyTypeFQN}>){ExpandConverterMethodName}(typeof({propertyTypeFQN}), new {converterFQN}(), {OptionsLocalVariableName})"; + } writer.WriteLine($$""" - var {{InfoVarName}}{{i}} = new {{JsonPropertyInfoValuesTypeRef}}<{{propertyTypeFQN}}>() + var {{InfoVarName}}{{i}} = new {{JsonPropertyInfoValuesTypeRef}}<{{propertyTypeFQN}}> { IsProperty = {{FormatBool(property.IsProperty)}}, IsPublic = {{FormatBool(property.IsPublic)}}, IsVirtual = {{FormatBool(property.IsVirtual)}}, DeclaringType = typeof({{property.DeclaringType.FullyQualifiedName}}), - Converter = {{converterInstantiationExpr}}, + Converter = {{converterInstantiationExpr ?? "null"}}, Getter = {{getterValue}}, Setter = {{setterValue}}, IgnoreCondition = {{ignoreConditionNamedArg}}, @@ -695,11 +733,7 @@ private void GenerateFastPathFuncForObject(SourceWriter writer, ContextGeneratio { string typeRef = typeGenSpec.TypeRef.FullyQualifiedName; - if (!TryFilterSerializableProps( - typeGenSpec, - contextSpec, - out Dictionary? serializableProperties, - out bool castingRequiredForProps)) + if (!TryFilterSerializableProps(typeGenSpec, contextSpec, out Dictionary? serializableProperties)) { // Type uses configuration that doesn't support fast-path: emit a stub that just throws. GenerateFastPathFuncHeader(writer, typeGenSpec, serializeMethodName, skipNullCheck: true); @@ -740,7 +774,13 @@ private void GenerateFastPathFuncForObject(SourceWriter writer, ContextGeneratio _propertyNames.TryAdd(runtimePropName, propNameVarName); DefaultCheckType defaultCheckType = GetDefaultCheckType(contextSpec, propertyGenSpec); - string? objectExpr = castingRequiredForProps ? $"(({propertyGenSpec.DeclaringType.FullyQualifiedName}){ValueVarName})" : ValueVarName; + + // For properties whose declared type differs from that of the serialized type + // perform an explicit cast -- this is to account for hidden properties or diamond ambiguity. + string? objectExpr = propertyGenSpec.DeclaringType != typeGenSpec.TypeRef + ? $"(({propertyGenSpec.DeclaringType.FullyQualifiedName}){ValueVarName})" + : ValueVarName; + string propValueExpr = $"{objectExpr}.{propertyGenSpec.NameSpecifiedInSourceCode}"; switch (defaultCheckType) @@ -824,7 +864,7 @@ private static string GetParameterizedCtorInvocationFunc(TypeGenerationSpec type const string ArgsVarName = "args"; - StringBuilder sb = new($"static ({ArgsVarName}) => new {typeGenerationSpec.TypeRef.FullyQualifiedName}("); + StringBuilder sb = new($"static {ArgsVarName} => new {typeGenerationSpec.TypeRef.FullyQualifiedName}("); if (parameters.Count > 0) { @@ -970,7 +1010,7 @@ private static DefaultCheckType GetDefaultCheckType(ContextGenerationSpec contex }; } - private static void GenerateTypeInfoProperty(SourceWriter writer, TypeGenerationSpec typeMetadata, string metadataInitSource) + private static void GenerateTypeInfoFactoryHeader(SourceWriter writer, TypeGenerationSpec typeMetadata) { string typeFQN = typeMetadata.TypeRef.FullyQualifiedName; string typeInfoPropertyName = typeMetadata.TypeInfoPropertyName; @@ -994,7 +1034,10 @@ private static void GenerateTypeInfoProperty(SourceWriter writer, TypeGeneration """); writer.Indentation += 2; - writer.WriteLine(metadataInitSource); + } + + private static void GenerateTypeInfoFactoryFooter(SourceWriter writer) + { writer.Indentation -= 2; // NB OriginatingResolver should be the last property set by the source generator. @@ -1002,12 +1045,12 @@ private static void GenerateTypeInfoProperty(SourceWriter writer, TypeGeneration } {{JsonTypeInfoReturnValueLocalVariableName}}.{{OriginatingResolverPropertyName}} = this; - return jsonTypeInfo; + return {{JsonTypeInfoReturnValueLocalVariableName}}; } """); } - private static SourceText GetRootJsonContextImplementation(ContextGenerationSpec contextSpec) + private static SourceText GetRootJsonContextImplementation(ContextGenerationSpec contextSpec, bool emitGetConverterForNullablePropertyMethod) { string contextTypeRef = contextSpec.ContextType.FullyQualifiedName; string contextTypeName = contextSpec.ContextType.Name; @@ -1048,7 +1091,7 @@ private static SourceText GetRootJsonContextImplementation(ContextGenerationSpec writer.WriteLine(); - GenerateConverterHelpers(writer); + GenerateConverterHelpers(writer, emitGetConverterForNullablePropertyMethod); return CompleteSourceFileAndReturnText(writer); } @@ -1082,7 +1125,7 @@ private static void GetLogicForDefaultSerializerOptionsInit(ContextGenerationSpe """); } - private static void GenerateConverterHelpers(SourceWriter writer) + private static void GenerateConverterHelpers(SourceWriter writer, bool emitGetConverterForNullablePropertyMethod) { // The generic type parameter could capture type parameters from containing types, // so use a name that is unlikely to be used. @@ -1109,15 +1152,20 @@ private static void GenerateConverterHelpers(SourceWriter writer) {{JsonConverterTypeRef}}? converter = options.Converters[i]; if (converter?.CanConvert(type) == true) { - return {{ExpandConverterMethodName}}(type, converter, options); + return {{ExpandConverterMethodName}}(type, converter, options, validateCanConvert: false); } } return null; } - private static {{JsonConverterTypeRef}} {{ExpandConverterMethodName}}({{TypeTypeRef}} type, {{JsonConverterTypeRef}} converter, {{JsonSerializerOptionsTypeRef}} options) + private static {{JsonConverterTypeRef}} {{ExpandConverterMethodName}}({{TypeTypeRef}} type, {{JsonConverterTypeRef}} converter, {{JsonSerializerOptionsTypeRef}} options, bool validateCanConvert = true) { + if (validateCanConvert && !converter.CanConvert(type)) + { + throw new {{InvalidOperationExceptionTypeRef}}(string.Format("{{ExceptionMessages.IncompatibleConverterType}}", converter.GetType(), type)); + } + if (converter is {{JsonConverterFactoryTypeRef}} factory) { converter = factory.CreateConverter(type, options); @@ -1126,15 +1174,29 @@ private static void GenerateConverterHelpers(SourceWriter writer) throw new {{InvalidOperationExceptionTypeRef}}(string.Format("{{ExceptionMessages.InvalidJsonConverterFactoryOutput}}", factory.GetType())); } } - - if (!converter.CanConvert(type)) - { - throw new {{InvalidOperationExceptionTypeRef}}(string.Format("{{ExceptionMessages.IncompatibleConverterType}}", converter.GetType(), type)); - } return converter; } """); + + if (emitGetConverterForNullablePropertyMethod) + { + writer.WriteLine($$""" + + private static {{JsonConverterTypeRef}}<{{TypeParameter}}?> {{GetConverterForNullablePropertyMethodName}}<{{TypeParameter}}>({{JsonConverterTypeRef}} converter, {{JsonSerializerOptionsTypeRef}} options) + where {{TypeParameter}} : struct + { + if (converter.CanConvert(typeof({{TypeParameter}}?))) + { + return ({{JsonConverterTypeRef}}<{{TypeParameter}}?>){{ExpandConverterMethodName}}(typeof({{TypeParameter}}?), converter, options, validateCanConvert: false); + } + + converter = {{ExpandConverterMethodName}}(typeof({{TypeParameter}}), converter, options); + {{JsonTypeInfoTypeRef}}<{{TypeParameter}}> typeInfo = {{JsonMetadataServicesTypeRef}}.{{CreateValueInfoMethodName}}<{{TypeParameter}}>(options, converter); + return {{JsonMetadataServicesTypeRef}}.GetNullableConverter<{{TypeParameter}}>(typeInfo); + } + """); + } } private static SourceText GetGetTypeInfoImplementation(ContextGenerationSpec contextSpec) @@ -1320,12 +1382,10 @@ private static bool IsGenerationModeSpecified(TypeGenerationSpec typeSpec, JsonS public static bool TryFilterSerializableProps( TypeGenerationSpec typeSpec, ContextGenerationSpec contextSpec, - [NotNullWhen(true)] out Dictionary? serializableProperties, - out bool castingRequiredForProps) + [NotNullWhen(true)] out Dictionary? serializableProperties) { Debug.Assert(typeSpec.PropertyGenSpecs != null); - castingRequiredForProps = false; serializableProperties = new Dictionary(); HashSet? ignoredMembers = null; @@ -1358,10 +1418,6 @@ public static bool TryFilterSerializableProps( continue; } - // Using properties from an interface hierarchy -- require explicit casting when - // getting properties in the fast path to account for possible diamond ambiguities. - castingRequiredForProps |= typeSpec.TypeRef.TypeKind is TypeKind.Interface && propGenSpec.PropertyType != typeSpec.TypeRef; - string memberName = propGenSpec.MemberName!; // The JsonPropertyNameAttribute or naming policy resulted in a collision. @@ -1419,12 +1475,10 @@ public static bool TryFilterSerializableProps( } Debug.Assert(typeSpec.PropertyGenSpecs.Count >= serializableProperties.Count); - castingRequiredForProps |= typeSpec.PropertyGenSpecs.Count > serializableProperties.Count; return true; ReturnFalse: serializableProperties = null; - castingRequiredForProps = false; return false; } diff --git a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs index 6fe2320dbe5ade..eba9ca2c642481 100644 --- a/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs +++ b/src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs @@ -131,7 +131,7 @@ public Parser(KnownTypeSymbols knownSymbols) TypeToGenerate typeToGenerate = _typesToGenerate.Dequeue(); if (!_generatedTypes.ContainsKey(typeToGenerate.Type)) { - TypeGenerationSpec spec = ParseTypeGenerationSpec(typeToGenerate, contextName: contextTypeSymbol.Name, contextLocation, options); + TypeGenerationSpec spec = ParseTypeGenerationSpec(typeToGenerate, contextTypeSymbol, contextLocation, options); _generatedTypes.Add(typeToGenerate.Type, spec); } } @@ -494,8 +494,10 @@ private static JsonSourceGenerationOptionsAttribute ParseJsonSourceGenerationOpt }; } - private TypeGenerationSpec ParseTypeGenerationSpec(TypeToGenerate typeToGenerate, string contextName, Location contextLocation, JsonSourceGenerationOptionsAttribute options) + private TypeGenerationSpec ParseTypeGenerationSpec(TypeToGenerate typeToGenerate, INamedTypeSymbol contextType, Location contextLocation, JsonSourceGenerationOptionsAttribute options) { + Debug.Assert(IsSymbolAccessibleWithin(typeToGenerate.Type, within: contextType), "should not generate metadata for inaccessible types."); + ITypeSymbol type = typeToGenerate.Type; Location typeLocation = type.GetDiagnosticLocation() ?? typeToGenerate.AttributeLocation ?? contextLocation; @@ -547,7 +549,7 @@ private TypeGenerationSpec ParseTypeGenerationSpec(TypeToGenerate typeToGenerate } else if (!foundDesignTimeCustomConverter && _knownSymbols.JsonConverterAttributeType.IsAssignableFrom(attributeType)) { - converterType = GetConverterTypeFromAttribute(attributeData); + converterType = GetConverterTypeFromAttribute(contextType, type, attributeData); foundDesignTimeCustomConverter = true; } @@ -589,179 +591,41 @@ private TypeGenerationSpec ParseTypeGenerationSpec(TypeToGenerate typeToGenerate { classType = ClassType.Enum; } - else if (type.GetCompatibleGenericBaseType(_knownSymbols.IAsyncEnumerableOfTType) is INamedTypeSymbol iasyncEnumerableType) + else if (TryResolveCollectionType(type, + out ITypeSymbol? valueType, + out ITypeSymbol? keyType, + out collectionType, + out immutableCollectionFactoryTypeFullName, + out bool needsRuntimeType)) { - if (type.CanUseDefaultConstructorForDeserialization(out IMethodSymbol? defaultCtor)) - { - constructionStrategy = ObjectConstructionStrategy.ParameterlessConstructor; - constructorSetsRequiredMembers = defaultCtor?.ContainsAttribute(SetsRequiredMembersAttributeFullName) == true; - } - - ITypeSymbol elementType = iasyncEnumerableType.TypeArguments[0]; - collectionValueType = EnqueueType(elementType, typeToGenerate.Mode); - collectionType = CollectionType.IAsyncEnumerableOfT; - classType = ClassType.Enumerable; - } - else if (_knownSymbols.IEnumerableType.IsAssignableFrom(type)) - { - if (type.CanUseDefaultConstructorForDeserialization(out IMethodSymbol? defaultCtor)) - { - constructionStrategy = ObjectConstructionStrategy.ParameterlessConstructor; - constructorSetsRequiredMembers = defaultCtor?.ContainsAttribute(SetsRequiredMembersAttributeFullName) == true; - } - - INamedTypeSymbol? actualTypeToConvert; - ITypeSymbol? keyType = null; - ITypeSymbol valueType; - bool needsRuntimeType = false; - - if (type is IArrayTypeSymbol arraySymbol) - { - Debug.Assert(arraySymbol.Rank == 1, "multi-dimensional arrays should have been handled earlier."); - classType = ClassType.Enumerable; - collectionType = CollectionType.Array; - valueType = arraySymbol.ElementType; - } - else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.ListOfTType)) != null) - { - classType = ClassType.Enumerable; - collectionType = CollectionType.List; - valueType = actualTypeToConvert.TypeArguments[0]; - } - else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.DictionaryOfTKeyTValueType)) != null) - { - classType = ClassType.Dictionary; - collectionType = CollectionType.Dictionary; - - keyType = actualTypeToConvert.TypeArguments[0]; - valueType = actualTypeToConvert.TypeArguments[1]; - } - else if (_knownSymbols.IsImmutableDictionaryType(type, out immutableCollectionFactoryTypeFullName)) - { - classType = ClassType.Dictionary; - collectionType = CollectionType.ImmutableDictionary; - - ImmutableArray genericArgs = ((INamedTypeSymbol)type).TypeArguments; - keyType = genericArgs[0]; - valueType = genericArgs[1]; - } - else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.IDictionaryOfTKeyTValueType)) != null) - { - classType = ClassType.Dictionary; - collectionType = CollectionType.IDictionaryOfTKeyTValue; - - keyType = actualTypeToConvert.TypeArguments[0]; - valueType = actualTypeToConvert.TypeArguments[1]; - - needsRuntimeType = SymbolEqualityComparer.Default.Equals(type, actualTypeToConvert); - } - else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.IReadonlyDictionaryOfTKeyTValueType)) != null) - { - classType = ClassType.Dictionary; - collectionType = CollectionType.IReadOnlyDictionary; - - keyType = actualTypeToConvert.TypeArguments[0]; - valueType = actualTypeToConvert.TypeArguments[1]; - - needsRuntimeType = SymbolEqualityComparer.Default.Equals(type, actualTypeToConvert); - } - else if (_knownSymbols.IsImmutableEnumerableType(type, out immutableCollectionFactoryTypeFullName)) - { - classType = ClassType.Enumerable; - collectionType = CollectionType.ImmutableEnumerable; - valueType = ((INamedTypeSymbol)type).TypeArguments[0]; - } - else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.IListOfTType)) != null) - { - classType = ClassType.Enumerable; - collectionType = CollectionType.IListOfT; - valueType = actualTypeToConvert.TypeArguments[0]; - } - else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.ISetOfTType)) != null) - { - classType = ClassType.Enumerable; - collectionType = CollectionType.ISet; - valueType = actualTypeToConvert.TypeArguments[0]; - } - else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.ICollectionOfTType)) != null) + if (!IsSymbolAccessibleWithin(valueType, within: contextType) || + (keyType != null && !IsSymbolAccessibleWithin(keyType, within: contextType))) { - classType = ClassType.Enumerable; - collectionType = CollectionType.ICollectionOfT; - valueType = actualTypeToConvert.TypeArguments[0]; - } - else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.StackOfTType)) != null) - { - classType = ClassType.Enumerable; - collectionType = CollectionType.StackOfT; - valueType = actualTypeToConvert.TypeArguments[0]; - } - else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.QueueOfTType)) != null) - { - classType = ClassType.Enumerable; - collectionType = CollectionType.QueueOfT; - valueType = actualTypeToConvert.TypeArguments[0]; - } - else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.ConcurrentStackType)) != null) - { - classType = ClassType.Enumerable; - collectionType = CollectionType.ConcurrentStack; - valueType = actualTypeToConvert.TypeArguments[0]; - } - else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.ConcurrentQueueType)) != null) - { - classType = ClassType.Enumerable; - collectionType = CollectionType.ConcurrentQueue; - valueType = actualTypeToConvert.TypeArguments[0]; - } - else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.IEnumerableOfTType)) != null) - { - classType = ClassType.Enumerable; - collectionType = CollectionType.IEnumerableOfT; - valueType = actualTypeToConvert.TypeArguments[0]; - } - else if (_knownSymbols.IDictionaryType.IsAssignableFrom(type)) - { - classType = ClassType.Dictionary; - collectionType = CollectionType.IDictionary; - keyType = _knownSymbols.StringType; - valueType = _knownSymbols.ObjectType; - - needsRuntimeType = SymbolEqualityComparer.Default.Equals(type, actualTypeToConvert); - } - else if (_knownSymbols.IListType.IsAssignableFrom(type)) - { - classType = ClassType.Enumerable; - collectionType = CollectionType.IList; - valueType = _knownSymbols.ObjectType; - } - else if (_knownSymbols.StackType.IsAssignableFrom(type)) - { - classType = ClassType.Enumerable; - collectionType = CollectionType.Stack; - valueType = _knownSymbols.ObjectType; - } - else if (_knownSymbols.QueueType.IsAssignableFrom(type)) - { - classType = ClassType.Enumerable; - collectionType = CollectionType.Queue; - valueType = _knownSymbols.ObjectType; + classType = ClassType.UnsupportedType; + keyType = valueType = null; + immutableCollectionFactoryTypeFullName = null; + collectionType = default; + needsRuntimeType = false; } else { - classType = ClassType.Enumerable; - collectionType = CollectionType.IEnumerable; - valueType = _knownSymbols.ObjectType; - } - - collectionValueType = EnqueueType(valueType, typeToGenerate.Mode); + if (type.CanUseDefaultConstructorForDeserialization(out IMethodSymbol? defaultCtor)) + { + constructionStrategy = ObjectConstructionStrategy.ParameterlessConstructor; + constructorSetsRequiredMembers = defaultCtor?.ContainsAttribute(SetsRequiredMembersAttributeFullName) == true; + } - if (keyType != null) - { - collectionKeyType = EnqueueType(keyType, typeToGenerate.Mode); + classType = keyType != null ? ClassType.Dictionary : ClassType.Enumerable; + collectionValueType = EnqueueType(valueType, typeToGenerate.Mode); - if (needsRuntimeType) + if (keyType != null) { - runtimeTypeRef = GetDictionaryTypeRef(keyType, valueType); + collectionKeyType = EnqueueType(keyType, typeToGenerate.Mode); + + if (needsRuntimeType) + { + runtimeTypeRef = GetDictionaryTypeRef(keyType, valueType); + } } } } @@ -825,8 +689,9 @@ private TypeGenerationSpec ParseTypeGenerationSpec(TypeToGenerate typeToGenerate foreach (INamedTypeSymbol currentType in type.GetSortedTypeHierarchy()) { var declaringTypeRef = new TypeRef(currentType); + ImmutableArray members = currentType.GetMembers(); - foreach (IPropertySymbol propertyInfo in currentType.GetMembers().OfType()) + foreach (IPropertySymbol propertyInfo in members.OfType()) { bool isVirtual = propertyInfo.IsVirtual(); @@ -840,7 +705,7 @@ private TypeGenerationSpec ParseTypeGenerationSpec(TypeToGenerate typeToGenerate continue; } - PropertyGenerationSpec? spec = ParsePropertyGenerationSpec(declaringTypeRef, propertyInfo.Type, propertyInfo, isVirtual, typeToGenerate.Mode, options); + PropertyGenerationSpec? spec = ParsePropertyGenerationSpec(contextType, declaringTypeRef, propertyInfo.Type, propertyInfo, isVirtual, typeToGenerate.Mode, options); if (spec is null) { continue; @@ -849,7 +714,7 @@ private TypeGenerationSpec ParseTypeGenerationSpec(TypeToGenerate typeToGenerate CacheMemberHelper(propertyInfo.Type, propertyInfo, spec); } - foreach (IFieldSymbol fieldInfo in currentType.GetMembers().OfType()) + foreach (IFieldSymbol fieldInfo in members.OfType()) { // Skip if : if ( @@ -865,7 +730,7 @@ private TypeGenerationSpec ParseTypeGenerationSpec(TypeToGenerate typeToGenerate continue; } - PropertyGenerationSpec? spec = ParsePropertyGenerationSpec(declaringTypeRef, fieldInfo.Type, fieldInfo, isVirtual: false, typeToGenerate.Mode, options); + PropertyGenerationSpec? spec = ParsePropertyGenerationSpec(contextType, declaringTypeRef, fieldInfo.Type, fieldInfo, isVirtual: false, typeToGenerate.Mode, options); if (spec is null) { continue; @@ -915,11 +780,6 @@ void CacheMemberHelper(ITypeSymbol memberType, ISymbol memberInfo, PropertyGener (propertyInitializers ??= new()).Add(propInitializerSpec); } } - - if (spec.HasJsonInclude && (!spec.CanUseGetter || !spec.CanUseSetter || !spec.IsPublic)) - { - ReportDiagnostic(DiagnosticDescriptors.InaccessibleJsonIncludePropertiesNotSupported, memberInfo.GetDiagnosticLocation(), new string[] { type.Name, spec.MemberName }); - } } } @@ -938,7 +798,7 @@ void CacheMemberHelper(ITypeSymbol memberType, ISymbol memberInfo, PropertyGener ReportDiagnostic(DiagnosticDescriptors.TypeNotSupported, typeLocation, new string[] { typeRef.FullyQualifiedName }); } - if (!_generatedContextAndTypeNames.Add((contextName, typeInfoPropertyName))) + if (!_generatedContextAndTypeNames.Add((contextType.Name, typeInfoPropertyName))) { // The context name/property name combination will result in a conflict in generated types. // Workaround for https://github.com/dotnet/roslyn/issues/54185 by keeping track of the file names we've used. @@ -976,6 +836,149 @@ void CacheMemberHelper(ITypeSymbol memberType, ISymbol memberInfo, PropertyGener }; } + private bool TryResolveCollectionType( + ITypeSymbol type, + [NotNullWhen(true)] out ITypeSymbol? valueType, + out ITypeSymbol? keyType, + out CollectionType collectionType, + out string? immutableCollectionFactoryTypeFullName, + out bool needsRuntimeType) + { + INamedTypeSymbol? actualTypeToConvert; + valueType = null; + keyType = null; + collectionType = default; + immutableCollectionFactoryTypeFullName = null; + needsRuntimeType = false; + + // IAsyncEnumerable takes precedence over IEnumerable. + if (type.GetCompatibleGenericBaseType(_knownSymbols.IAsyncEnumerableOfTType) is INamedTypeSymbol iAsyncEnumerableType) + { + valueType = iAsyncEnumerableType.TypeArguments[0]; + collectionType = CollectionType.IAsyncEnumerableOfT; + return true; + } + + if (!_knownSymbols.IEnumerableType.IsAssignableFrom(type)) + { + // Type is not IEnumerable and therefore not a collection type + return false; + } + + if (type is IArrayTypeSymbol arraySymbol) + { + Debug.Assert(arraySymbol.Rank == 1, "multi-dimensional arrays should have been handled earlier."); + collectionType = CollectionType.Array; + valueType = arraySymbol.ElementType; + } + else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.ListOfTType)) != null) + { + collectionType = CollectionType.List; + valueType = actualTypeToConvert.TypeArguments[0]; + } + else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.DictionaryOfTKeyTValueType)) != null) + { + collectionType = CollectionType.Dictionary; + keyType = actualTypeToConvert.TypeArguments[0]; + valueType = actualTypeToConvert.TypeArguments[1]; + } + else if (_knownSymbols.IsImmutableDictionaryType(type, out immutableCollectionFactoryTypeFullName)) + { + collectionType = CollectionType.ImmutableDictionary; + ImmutableArray genericArgs = ((INamedTypeSymbol)type).TypeArguments; + keyType = genericArgs[0]; + valueType = genericArgs[1]; + } + else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.IDictionaryOfTKeyTValueType)) != null) + { + collectionType = CollectionType.IDictionaryOfTKeyTValue; + keyType = actualTypeToConvert.TypeArguments[0]; + valueType = actualTypeToConvert.TypeArguments[1]; + needsRuntimeType = SymbolEqualityComparer.Default.Equals(type, actualTypeToConvert); + } + else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.IReadonlyDictionaryOfTKeyTValueType)) != null) + { + collectionType = CollectionType.IReadOnlyDictionary; + keyType = actualTypeToConvert.TypeArguments[0]; + valueType = actualTypeToConvert.TypeArguments[1]; + needsRuntimeType = SymbolEqualityComparer.Default.Equals(type, actualTypeToConvert); + } + else if (_knownSymbols.IsImmutableEnumerableType(type, out immutableCollectionFactoryTypeFullName)) + { + collectionType = CollectionType.ImmutableEnumerable; + valueType = ((INamedTypeSymbol)type).TypeArguments[0]; + } + else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.IListOfTType)) != null) + { + collectionType = CollectionType.IListOfT; + valueType = actualTypeToConvert.TypeArguments[0]; + } + else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.ISetOfTType)) != null) + { + collectionType = CollectionType.ISet; + valueType = actualTypeToConvert.TypeArguments[0]; + } + else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.ICollectionOfTType)) != null) + { + collectionType = CollectionType.ICollectionOfT; + valueType = actualTypeToConvert.TypeArguments[0]; + } + else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.StackOfTType)) != null) + { + collectionType = CollectionType.StackOfT; + valueType = actualTypeToConvert.TypeArguments[0]; + } + else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.QueueOfTType)) != null) + { + collectionType = CollectionType.QueueOfT; + valueType = actualTypeToConvert.TypeArguments[0]; + } + else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.ConcurrentStackType)) != null) + { + collectionType = CollectionType.ConcurrentStack; + valueType = actualTypeToConvert.TypeArguments[0]; + } + else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.ConcurrentQueueType)) != null) + { + collectionType = CollectionType.ConcurrentQueue; + valueType = actualTypeToConvert.TypeArguments[0]; + } + else if ((actualTypeToConvert = type.GetCompatibleGenericBaseType(_knownSymbols.IEnumerableOfTType)) != null) + { + collectionType = CollectionType.IEnumerableOfT; + valueType = actualTypeToConvert.TypeArguments[0]; + } + else if (_knownSymbols.IDictionaryType.IsAssignableFrom(type)) + { + collectionType = CollectionType.IDictionary; + keyType = _knownSymbols.StringType; + valueType = _knownSymbols.ObjectType; + needsRuntimeType = SymbolEqualityComparer.Default.Equals(type, actualTypeToConvert); + } + else if (_knownSymbols.IListType.IsAssignableFrom(type)) + { + collectionType = CollectionType.IList; + valueType = _knownSymbols.ObjectType; + } + else if (_knownSymbols.StackType.IsAssignableFrom(type)) + { + collectionType = CollectionType.Stack; + valueType = _knownSymbols.ObjectType; + } + else if (_knownSymbols.QueueType.IsAssignableFrom(type)) + { + collectionType = CollectionType.Queue; + valueType = _knownSymbols.ObjectType; + } + else + { + collectionType = CollectionType.IEnumerable; + valueType = _knownSymbols.ObjectType; + } + + return true; + } + private TypeRef? GetDictionaryTypeRef(ITypeSymbol keyType, ITypeSymbol valueType) { INamedTypeSymbol? dictionary = _knownSymbols.DictionaryOfTKeyTValueType?.Construct(keyType, valueType); @@ -1011,7 +1014,7 @@ private static void CacheMember( if (propGenSpec.DefaultIgnoreCondition == JsonIgnoreCondition.Always) { ignoredMembers ??= new(); - ignoredMembers.Add(propGenSpec.MemberName, memberInfo); + ignoredMembers[propGenSpec.MemberName] = memberInfo; } } @@ -1040,6 +1043,7 @@ private static bool PropertyIsOverriddenAndIgnored( } private PropertyGenerationSpec? ParsePropertyGenerationSpec( + INamedTypeSymbol contextType, TypeRef declaringType, ITypeSymbol memberType, ISymbol memberInfo, @@ -1050,6 +1054,7 @@ private static bool PropertyIsOverriddenAndIgnored( Debug.Assert(memberInfo is IFieldSymbol or IPropertySymbol); ProcessMemberCustomAttributes( + contextType, memberInfo, out bool hasJsonInclude, out string? jsonPropertyName, @@ -1062,6 +1067,7 @@ private static bool PropertyIsOverriddenAndIgnored( out bool hasJsonRequiredAttribute); ProcessMember( + contextType, memberInfo, hasJsonInclude, out bool isReadOnly, @@ -1069,14 +1075,22 @@ private static bool PropertyIsOverriddenAndIgnored( out bool isRequired, out bool canUseGetter, out bool canUseSetter, + out bool hasJsonIncludeButIsInaccessible, out bool setterIsInitOnly); - if (!isPublic && !memberType.IsPublic()) + if (hasJsonIncludeButIsInaccessible) { - return null; + ReportDiagnostic(DiagnosticDescriptors.InaccessibleJsonIncludePropertiesNotSupported, memberInfo.GetDiagnosticLocation(), new string[] { declaringType.Name, memberInfo.Name }); } - bool needsAtSign = memberInfo.MemberNameNeedsAtSign(); + if ((!canUseGetter && !canUseSetter && !hasJsonIncludeButIsInaccessible) || + !IsSymbolAccessibleWithin(memberType, within: contextType)) + { + // Skip the member if either of the two conditions hold + // 1. Member has no accessible getters or setters (but is not marked with JsonIncludeAttribute since we need to throw a runtime exception) OR + // 2. The member type is not accessible within the generated context. + return null; + } string clrName = memberInfo.Name; string runtimePropertyName = DetermineRuntimePropName(clrName, jsonPropertyName, options.PropertyNamingPolicy); @@ -1084,7 +1098,7 @@ private static bool PropertyIsOverriddenAndIgnored( return new PropertyGenerationSpec { - NameSpecifiedInSourceCode = needsAtSign ? "@" + memberInfo.Name : memberInfo.Name, + NameSpecifiedInSourceCode = memberInfo.MemberNameNeedsAtSign() ? "@" + memberInfo.Name : memberInfo.Name, MemberName = memberInfo.Name, IsProperty = memberInfo is IPropertySymbol, IsPublic = isPublic, @@ -1111,6 +1125,7 @@ private static bool PropertyIsOverriddenAndIgnored( } private void ProcessMemberCustomAttributes( + INamedTypeSymbol contextType, ISymbol memberInfo, out bool hasJsonInclude, out string? jsonPropertyName, @@ -1145,7 +1160,7 @@ private void ProcessMemberCustomAttributes( if (converterType is null && _knownSymbols.JsonConverterAttributeType.IsAssignableFrom(attributeType)) { - converterType = GetConverterTypeFromAttribute(attributeData); + converterType = GetConverterTypeFromAttribute(contextType, memberInfo, attributeData); } else if (attributeType.ContainingAssembly.Name == SystemTextJsonNamespace) { @@ -1213,7 +1228,8 @@ private void ProcessMemberCustomAttributes( } } - private static void ProcessMember( + private void ProcessMember( + INamedTypeSymbol contextType, ISymbol memberInfo, bool hasJsonInclude, out bool isReadOnly, @@ -1221,13 +1237,16 @@ private static void ProcessMember( out bool isRequired, out bool canUseGetter, out bool canUseSetter, - out bool setterIsInitOnly) + out bool hasJsonIncludeButIsInaccessible, + out bool isSetterInitOnly) { isPublic = false; + isReadOnly = false; isRequired = false; canUseGetter = false; canUseSetter = false; - setterIsInitOnly = false; + hasJsonIncludeButIsInaccessible = false; + isSetterInitOnly = false; switch (memberInfo) { @@ -1246,26 +1265,33 @@ private static void ProcessMember( isPublic = true; canUseGetter = true; } - else if (getMethod.DeclaredAccessibility is Accessibility.Internal) + else if (IsSymbolAccessibleWithin(getMethod, within: contextType)) { canUseGetter = hasJsonInclude; } + else + { + hasJsonIncludeButIsInaccessible = hasJsonInclude; + } } if (setMethod != null) { - isReadOnly = false; - setterIsInitOnly = setMethod.IsInitOnly; + isSetterInitOnly = setMethod.IsInitOnly; if (setMethod.DeclaredAccessibility is Accessibility.Public) { isPublic = true; canUseSetter = true; } - else if (setMethod.DeclaredAccessibility is Accessibility.Internal) + else if (IsSymbolAccessibleWithin(setMethod, within: contextType)) { canUseSetter = hasJsonInclude; } + else + { + hasJsonIncludeButIsInaccessible = hasJsonInclude; + } } else { @@ -1275,39 +1301,46 @@ private static void ProcessMember( break; case IFieldSymbol fieldInfo: { - isPublic = fieldInfo.DeclaredAccessibility is Accessibility.Public; isReadOnly = fieldInfo.IsReadOnly; #if ROSLYN4_4_OR_GREATER isRequired = fieldInfo.IsRequired; #endif - if (fieldInfo.DeclaredAccessibility is not (Accessibility.Private or Accessibility.Protected)) + if (fieldInfo.DeclaredAccessibility is Accessibility.Public) { + isPublic = true; canUseGetter = true; canUseSetter = !isReadOnly; } + else + { + // Unlike properties JsonIncludeAttribute is not supported for internal fields. + hasJsonIncludeButIsInaccessible = hasJsonInclude; + } } break; default: - throw new InvalidOperationException(); + Debug.Fail("Method given an invalid symbol type."); + break; } } - private static bool PropertyAccessorCanBeReferenced(MethodInfo? accessor) - => accessor != null && (accessor.IsPublic || accessor.IsAssembly); - - private TypeRef? GetConverterTypeFromAttribute(AttributeData attributeData) + private TypeRef? GetConverterTypeFromAttribute(INamedTypeSymbol contextType, ISymbol declaringSymbol, AttributeData attributeData) { Debug.Assert(_knownSymbols.JsonConverterAttributeType.IsAssignableFrom(attributeData.AttributeClass)); var converterType = (INamedTypeSymbol?)attributeData.ConstructorArguments[0].Value; if (converterType == null || !_knownSymbols.JsonConverterType.IsAssignableFrom(converterType) || - !converterType.Constructors.Any(c => c.Parameters.Length == 0) || - converterType.IsNestedPrivate()) + !converterType.Constructors.Any(c => c.Parameters.Length == 0 && IsSymbolAccessibleWithin(c, within: contextType))) { return null; } + if (_knownSymbols.JsonStringEnumConverterType.IsAssignableFrom(converterType)) + { + ReportDiagnostic(DiagnosticDescriptors.JsonStringEnumConverterNotSupportedInAot, declaringSymbol.GetDiagnosticLocation(), declaringSymbol.ToDisplayString()); + } + return new TypeRef(converterType); } @@ -1502,6 +1535,9 @@ private static bool TryGetDeserializationConstructor( return true; } + private bool IsSymbolAccessibleWithin(ISymbol symbol, INamedTypeSymbol within) + => _knownSymbols.Compilation.IsSymbolAccessibleWithin(symbol, within); + private bool IsUnsupportedType(ITypeSymbol type) { return @@ -1510,6 +1546,8 @@ private bool IsUnsupportedType(ITypeSymbol type) SymbolEqualityComparer.Default.Equals(_knownSymbols.UIntPtrType, type) || _knownSymbols.MemberInfoType.IsAssignableFrom(type) || _knownSymbols.DelegateType.IsAssignableFrom(type) || + SymbolEqualityComparer.Default.Equals(type.OriginalDefinition, _knownSymbols.MemoryType) || + SymbolEqualityComparer.Default.Equals(type.OriginalDefinition, _knownSymbols.ReadOnlyMemoryType) || type is IArrayTypeSymbol { Rank: > 1 }; } diff --git a/src/libraries/System.Text.Json/gen/Resources/Strings.resx b/src/libraries/System.Text.Json/gen/Resources/Strings.resx index 4b0e51d66f1927..0af8900f499679 100644 --- a/src/libraries/System.Text.Json/gen/Resources/Strings.resx +++ b/src/libraries/System.Text.Json/gen/Resources/Strings.resx @@ -171,4 +171,10 @@ Type '{0}' is annotated with 'JsonDerivedTypeAttribute' which is not supported in 'JsonSourceGenerationMode.Serialization'. + + The non-generic 'JsonStringEnumConverter' requires dynamic code. + + + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.cs.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.cs.xlf index 80c44da5b530bd..f1fb86b5d772f5 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.cs.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.cs.xlf @@ -62,6 +62,16 @@ Deserializace vlastností pouze pro inicializaci se v současnosti v režimu generování zdroje nepodporuje. + + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + + + + The non-generic 'JsonStringEnumConverter' requires dynamic code. + The non-generic 'JsonStringEnumConverter' requires dynamic code. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. Typ {0} má více konstruktorů anotovaných s JsonConstructorAttribute. diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.de.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.de.xlf index 14848a3323a3d8..e50a30a16f1bf1 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.de.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.de.xlf @@ -62,6 +62,16 @@ Die Deserialisierung von reinen init-Eigenschaften wird im Quellgenerierungsmodus derzeit nicht unterstützt. + + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + + + + The non-generic 'JsonStringEnumConverter' requires dynamic code. + The non-generic 'JsonStringEnumConverter' requires dynamic code. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. Typ "{0}" weist mehrere Konstruktoren mit dem Kommentar "JsonConstructorAttribute" auf. diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.es.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.es.xlf index 8a97e745426f52..d3c411612685ee 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.es.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.es.xlf @@ -62,6 +62,16 @@ Actualmente no se admite la deserialización de propiedades de solo inicialización en el modo de generación de origen. + + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + + + + The non-generic 'JsonStringEnumConverter' requires dynamic code. + The non-generic 'JsonStringEnumConverter' requires dynamic code. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. El tipo '{0}' tiene varios constructores anotados con 'JsonConstructorAttribute'. diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.fr.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.fr.xlf index fb3db75c98c968..304d94c57830e9 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.fr.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.fr.xlf @@ -62,6 +62,16 @@ La désérialisation des propriétés d’initialisation uniquement n’est actuellement pas prise en charge en mode de génération de source. + + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + + + + The non-generic 'JsonStringEnumConverter' requires dynamic code. + The non-generic 'JsonStringEnumConverter' requires dynamic code. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. Le type' {0} 'a plusieurs constructeurs annotés avec’JsonConstructorAttribute'. diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.it.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.it.xlf index 596de184835bc8..d3aca5c082ac6c 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.it.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.it.xlf @@ -62,6 +62,16 @@ La deserializzazione delle proprietà di sola inizializzazione al momento non è supportata nella modalità di generazione di origine. + + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + + + + The non-generic 'JsonStringEnumConverter' requires dynamic code. + The non-generic 'JsonStringEnumConverter' requires dynamic code. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. Il tipo '{0}' contiene più costruttori che presentano l'annotazione 'JsonConstructorAttribute'. diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ja.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ja.xlf index 8988ba02b1b4a1..fe079b21ffcbe1 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ja.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ja.xlf @@ -62,6 +62,16 @@ 現在、ソース生成モードでは init-only プロパティの逆シリアル化はサポートされていません。 + + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + + + + The non-generic 'JsonStringEnumConverter' requires dynamic code. + The non-generic 'JsonStringEnumConverter' requires dynamic code. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. 型 '{0}' には、'JsonConstructorAttribute' で注釈が付けられた複数のコンストラクターがあります。 diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ko.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ko.xlf index 193d95b19fe917..81b05904e5faef 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ko.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ko.xlf @@ -62,6 +62,16 @@ 초기화 전용 속성의 역직렬화는 현재 원본 생성 모드에서 지원되지 않습니다. + + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + + + + The non-generic 'JsonStringEnumConverter' requires dynamic code. + The non-generic 'JsonStringEnumConverter' requires dynamic code. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. '{0}' 형식에 'JsonConstructorAttribute'로 주석이 추가된 여러 생성자가 있습니다. diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pl.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pl.xlf index e769635b39cb64..23db1eca71c6f4 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pl.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pl.xlf @@ -62,6 +62,16 @@ Deserializacja właściwości tylko do inicjowania nie jest obecnie obsługiwana w trybie generowania źródła. + + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + + + + The non-generic 'JsonStringEnumConverter' requires dynamic code. + The non-generic 'JsonStringEnumConverter' requires dynamic code. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. Typ "{0}" ma wiele konstruktorów z adnotacją "JsonConstructorAttribute". diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pt-BR.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pt-BR.xlf index 5ec4bae3fd5e76..8339db7173b812 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pt-BR.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.pt-BR.xlf @@ -62,6 +62,16 @@ A desserialização de propriedades apenas de inicialização não é atualmente suportada no modo de geração de origem. + + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + + + + The non-generic 'JsonStringEnumConverter' requires dynamic code. + The non-generic 'JsonStringEnumConverter' requires dynamic code. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. O tipo '{0}' tem vários construtores anotados com 'JsonConstructorAttribute'. diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ru.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ru.xlf index 5de2a8052b5eb4..e5ef15b58ec6b1 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ru.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.ru.xlf @@ -62,6 +62,16 @@ Десериализация свойств, предназначенных только для инициализации, сейчас не поддерживается в режиме создания исходного кода. + + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + + + + The non-generic 'JsonStringEnumConverter' requires dynamic code. + The non-generic 'JsonStringEnumConverter' requires dynamic code. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. Тип "{0}" имеет несколько конструкторов, аннотированных с использованием JsonConstructorAttribute. diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.tr.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.tr.xlf index f65e768d61a66f..8076c29dd62ad7 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.tr.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.tr.xlf @@ -62,6 +62,16 @@ Yalnızca başlangıç özelliklerini seri durumdan çıkarma şu anda kaynak oluşturma modunda desteklenmiyor. + + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + + + + The non-generic 'JsonStringEnumConverter' requires dynamic code. + The non-generic 'JsonStringEnumConverter' requires dynamic code. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. '{0}' türünün 'JsonConstructorAttribute' ile açıklanan birden çok oluşturucusu var. diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hans.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hans.xlf index 6f6087b8df9720..4b238b28974c61 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hans.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hans.xlf @@ -62,6 +62,16 @@ 源生成模式当前不支持仅初始化属性的反序列化。 + + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + + + + The non-generic 'JsonStringEnumConverter' requires dynamic code. + The non-generic 'JsonStringEnumConverter' requires dynamic code. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. 类型“{0}”具有用 “JsonConstructorAttribute” 批注的多个构造函数。 diff --git a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hant.xlf b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hant.xlf index 45bce60c24835f..fa0441766bb05d 100644 --- a/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hant.xlf +++ b/src/libraries/System.Text.Json/gen/Resources/xlf/Strings.zh-Hant.xlf @@ -62,6 +62,16 @@ 來源產生模式目前不支援 init-only 屬性的還原序列化。 + + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + The member '{0}' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter<TEnum>' instead. + + + + The non-generic 'JsonStringEnumConverter' requires dynamic code. + The non-generic 'JsonStringEnumConverter' requires dynamic code. + + Type '{0}' has multiple constructors annotated with 'JsonConstructorAttribute'. 類型 '{0}' 包含多個以 'JsonConstructorAttribute' 註解的建構函式。 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 e25bbc8164ada1..7974eb6707e315 100644 --- a/src/libraries/System.Text.Json/ref/System.Text.Json.cs +++ b/src/libraries/System.Text.Json/ref/System.Text.Json.cs @@ -1040,7 +1040,7 @@ public JsonSourceGenerationOptionsAttribute() { } public System.Text.Json.Serialization.JsonKnownNamingPolicy PropertyNamingPolicy { get { throw null; } set { } } public bool WriteIndented { get { throw null; } set { } } } - [System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute("JsonStringEnumConverter cannot be statically analyzed and requires runtime code generation. Consider authoring a custom converter that is not a factory to work around the issue. See https://github.com/dotnet/runtime/issues/73124.")] + [System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute("JsonStringEnumConverter cannot be statically analyzed and requires runtime code generation. Applications should use the generic JsonStringEnumConverter instead.")] public partial class JsonStringEnumConverter : System.Text.Json.Serialization.JsonConverterFactory { public JsonStringEnumConverter() { } @@ -1048,6 +1048,13 @@ public JsonStringEnumConverter(System.Text.Json.JsonNamingPolicy? namingPolicy = public sealed override bool CanConvert(System.Type typeToConvert) { throw null; } public sealed override System.Text.Json.Serialization.JsonConverter CreateConverter(System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { throw null; } } + public partial class JsonStringEnumConverter : System.Text.Json.Serialization.JsonConverterFactory where TEnum : struct, System.Enum + { + public JsonStringEnumConverter() { } + public JsonStringEnumConverter(System.Text.Json.JsonNamingPolicy? namingPolicy = null, bool allowIntegerValues = true) { } + public sealed override bool CanConvert(System.Type typeToConvert) { throw null; } + public sealed override System.Text.Json.Serialization.JsonConverter CreateConverter(System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { throw null; } + } public enum JsonUnknownDerivedTypeHandling { FailSerialization = 0, @@ -1183,7 +1190,7 @@ public static partial class JsonMetadataServices public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateStackInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo, System.Action addFunc) where TCollection : System.Collections.IEnumerable { throw null; } public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateStackInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.Metadata.JsonCollectionInfoValues collectionInfo) where TCollection : System.Collections.Generic.Stack { throw null; } public static System.Text.Json.Serialization.Metadata.JsonTypeInfo CreateValueInfo(System.Text.Json.JsonSerializerOptions options, System.Text.Json.Serialization.JsonConverter converter) { throw null; } - public static System.Text.Json.Serialization.JsonConverter GetEnumConverter(System.Text.Json.JsonSerializerOptions options) where T : struct { throw null; } + public static System.Text.Json.Serialization.JsonConverter GetEnumConverter(System.Text.Json.JsonSerializerOptions options) where T : struct, System.Enum { throw null; } public static System.Text.Json.Serialization.JsonConverter GetNullableConverter(System.Text.Json.JsonSerializerOptions options) where T : struct { throw null; } public static System.Text.Json.Serialization.JsonConverter GetNullableConverter(System.Text.Json.Serialization.Metadata.JsonTypeInfo underlyingTypeInfo) where T : struct { throw null; } public static System.Text.Json.Serialization.JsonConverter GetUnsupportedTypeConverter() { throw null; } diff --git a/src/libraries/System.Text.Json/src/CompatibilitySuppressions.xml b/src/libraries/System.Text.Json/src/CompatibilitySuppressions.xml new file mode 100644 index 00000000000000..1de43a6d616778 --- /dev/null +++ b/src/libraries/System.Text.Json/src/CompatibilitySuppressions.xml @@ -0,0 +1,11 @@ + + + + + CP0015 + T:System.Text.Json.Serialization.JsonStringEnumConverter:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + lib/net7.0/System.Text.Json.dll + lib/net7.0/System.Text.Json.dll + true + + \ No newline at end of file diff --git a/src/libraries/System.Text.Json/src/Resources/Strings.resx b/src/libraries/System.Text.Json/src/Resources/Strings.resx index 279368734cbdcc..064094dac3a4d5 100644 --- a/src/libraries/System.Text.Json/src/Resources/Strings.resx +++ b/src/libraries/System.Text.Json/src/Resources/Strings.resx @@ -549,6 +549,9 @@ The converter '{0}' cannot return an instance of JsonConverterFactory. + + The type '{0}' is not supported by the current JsonConverterFactory. + The element must be of type '{0}' diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/CastingConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/CastingConverter.cs index 3d6ff9b517f3b8..ece620785eb6ff 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/CastingConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/CastingConverter.cs @@ -19,7 +19,7 @@ internal sealed class CastingConverter : JsonConverter public override bool HandleNull { get; } internal override bool SupportsCreateObjectDelegate => _sourceConverter.SupportsCreateObjectDelegate; - internal CastingConverter(JsonConverter sourceConverter, bool handleNull, bool handleNullOnRead, bool handleNullOnWrite) + internal CastingConverter(JsonConverter sourceConverter) { Debug.Assert(typeof(T).IsInSubtypeRelationshipWith(sourceConverter.TypeToConvert)); Debug.Assert(sourceConverter.SourceConverterForCastingConverter is null, "casting converters should not be layered."); @@ -31,9 +31,9 @@ internal CastingConverter(JsonConverter sourceConverter, bool handleNull, bool h CanBePolymorphic = sourceConverter.CanBePolymorphic; // Ensure HandleNull values reflect the exact configuration of the source converter - HandleNullOnRead = handleNullOnRead; - HandleNullOnWrite = handleNullOnWrite; - HandleNull = handleNull; + HandleNullOnRead = sourceConverter.HandleNullOnRead; + HandleNullOnWrite = sourceConverter.HandleNullOnWrite; + HandleNull = sourceConverter.HandleNullOnWrite; } internal override JsonConverter? SourceConverterForCastingConverter => _sourceConverter; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectConverter.cs index 3a9ca0a301fbbd..4b61f2d764e06e 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectConverter.cs @@ -3,32 +3,32 @@ using System.Diagnostics; using System.Text.Json.Nodes; +using System.Text.Json.Serialization.Metadata; namespace System.Text.Json.Serialization.Converters { - internal sealed class ObjectConverter : JsonConverter + internal abstract class ObjectConverter : JsonConverter { private protected override ConverterStrategy GetDefaultConverterStrategy() => ConverterStrategy.Object; public ObjectConverter() { CanBePolymorphic = true; - // JsonElement/JsonNode parsing does not support async; force read ahead for now. - RequiresReadAhead = true; } - public override object? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + public sealed override object ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { - if (options.UnknownTypeHandling == JsonUnknownTypeHandling.JsonElement) - { - return JsonElement.ParseValue(ref reader); - } + ThrowHelper.ThrowNotSupportedException_DictionaryKeyTypeNotSupported(TypeToConvert, this); + return null!; + } - Debug.Assert(options.UnknownTypeHandling == JsonUnknownTypeHandling.JsonNode); - return JsonNodeConverter.Instance.Read(ref reader, typeToConvert, options); + internal sealed override object ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + ThrowHelper.ThrowNotSupportedException_DictionaryKeyTypeNotSupported(TypeToConvert, this); + return null!; } - public override void Write(Utf8JsonWriter writer, object? value, JsonSerializerOptions options) + public sealed override void Write(Utf8JsonWriter writer, object? value, JsonSerializerOptions options) { if (value is null) { @@ -40,6 +40,73 @@ public override void Write(Utf8JsonWriter writer, object? value, JsonSerializerO writer.WriteEndObject(); } + public sealed override void WriteAsPropertyName(Utf8JsonWriter writer, object value, JsonSerializerOptions options) + { + WriteAsPropertyNameCore(writer, value, options, isWritingExtensionDataProperty: false); + } + + internal sealed override void WriteAsPropertyNameCore(Utf8JsonWriter writer, object value, JsonSerializerOptions options, bool isWritingExtensionDataProperty) + { + if (value is null) + { + ThrowHelper.ThrowArgumentNullException(nameof(value)); + } + + Type runtimeType = value.GetType(); + if (runtimeType == TypeToConvert) + { + ThrowHelper.ThrowNotSupportedException_DictionaryKeyTypeNotSupported(runtimeType, this); + } + + JsonConverter runtimeConverter = options.GetConverterInternal(runtimeType); + runtimeConverter.WriteAsPropertyNameCoreAsObject(writer, value, options, isWritingExtensionDataProperty); + } + } + + /// + /// Defines an object converter that only supports (polymorphic) serialization but not deserialization. + /// This is done to avoid rooting dependencies to JsonNode/JsonElement necessary to drive object deserialization. + /// Source generator users need to explicitly declare support for object so that the derived converter gets used. + /// + internal sealed class SlimObjectConverter : ObjectConverter + { + // Keep track of the originating resolver so that the converter surfaces + // an accurate error message whenever deserialization is attempted. + private readonly IJsonTypeInfoResolver _originatingResolver; + + public SlimObjectConverter(IJsonTypeInfoResolver originatingResolver) + => _originatingResolver = originatingResolver; + + public override object? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + ThrowHelper.ThrowNotSupportedException_NoMetadataForType(typeToConvert, _originatingResolver); + return null; + } + } + + /// + /// Defines an object converter that supports deserialization via JsonElement/JsonNode representations. + /// Used as the default in reflection or if object is declared in the JsonSerializerContext type graph. + /// + internal sealed class DefaultObjectConverter : ObjectConverter + { + public DefaultObjectConverter() + { + // JsonElement/JsonNode parsing does not support async; force read ahead for now. + RequiresReadAhead = true; + } + + public override object? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (options.UnknownTypeHandling == JsonUnknownTypeHandling.JsonElement) + { + return JsonElement.ParseValue(ref reader); + } + + Debug.Assert(options.UnknownTypeHandling == JsonUnknownTypeHandling.JsonNode); + return JsonNodeConverter.Instance.Read(ref reader, typeToConvert, options); + } + internal override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options, scoped ref ReadStack state, out object? value) { object? referenceValue; @@ -78,64 +145,5 @@ internal override bool OnTryRead(ref Utf8JsonReader reader, Type typeToConvert, return true; } - - public override object ReadAsPropertyName(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - ThrowHelper.ThrowNotSupportedException_DictionaryKeyTypeNotSupported(TypeToConvert, this); - return null!; - } - - internal override object ReadAsPropertyNameCore(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - ThrowHelper.ThrowNotSupportedException_DictionaryKeyTypeNotSupported(TypeToConvert, this); - return null!; - } - - public override void WriteAsPropertyName(Utf8JsonWriter writer, object value, JsonSerializerOptions options) - { - WriteAsPropertyNameCore(writer, value, options, isWritingExtensionDataProperty: false); - } - - internal override void WriteAsPropertyNameCore(Utf8JsonWriter writer, object value, JsonSerializerOptions options, bool isWritingExtensionDataProperty) - { - if (value is null) - { - ThrowHelper.ThrowArgumentNullException(nameof(value)); - } - - Type runtimeType = value.GetType(); - JsonConverter runtimeConverter = options.GetConverterInternal(runtimeType); - if (runtimeConverter == this) - { - ThrowHelper.ThrowNotSupportedException_DictionaryKeyTypeNotSupported(runtimeType, this); - } - - runtimeConverter.WriteAsPropertyNameCoreAsObject(writer, value, options, isWritingExtensionDataProperty); - } - } - - /// - /// A placeholder ObjectConverter used for driving object root value - /// serialization only and does not root JsonNode/JsonDocument. - /// - internal sealed class ObjectConverterSlim : JsonConverter - { - private protected override ConverterStrategy GetDefaultConverterStrategy() => ConverterStrategy.Object; - - public ObjectConverterSlim() - { - CanBePolymorphic = true; - } - - public override object? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - { - Debug.Fail("Converter should only be used to drive root-level object serialization."); - return null; - } - - public override void Write(Utf8JsonWriter writer, object? value, JsonSerializerOptions options) - { - Debug.Fail("Converter should only be used to drive root-level object serialization."); - } } } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Large.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Large.cs index e34aae0a75e4ca..b00661bd568f45 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Large.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Object/ObjectWithParameterizedConstructorConverter.Large.cs @@ -17,9 +17,8 @@ internal class LargeObjectWithParameterizedConstructorConverter : ObjectWithP protected sealed override bool ReadAndCacheConstructorArgument(scoped ref ReadStack state, ref Utf8JsonReader reader, JsonParameterInfo jsonParameterInfo) { Debug.Assert(jsonParameterInfo.ShouldDeserialize); - Debug.Assert(jsonParameterInfo.Options != null); - bool success = jsonParameterInfo.EffectiveConverter.TryReadAsObject(ref reader, TypeToConvert, jsonParameterInfo.Options!, ref state, out object? arg); + bool success = jsonParameterInfo.EffectiveConverter.TryReadAsObject(ref reader, jsonParameterInfo.ParameterType, jsonParameterInfo.Options, ref state, out object? arg); if (success && !(arg == null && jsonParameterInfo.IgnoreNullTokensOnRead)) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DateOnlyConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DateOnlyConverter.cs index 16b4e5e82ec6d1..9917f47fcf8db6 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DateOnlyConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/DateOnlyConverter.cs @@ -57,7 +57,11 @@ private static DateOnly ReadCore(ref Utf8JsonReader reader) public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options) { +#if NET8_0_OR_GREATER + Span buffer = stackalloc byte[FormatLength]; +#else Span buffer = stackalloc char[FormatLength]; +#endif bool formattedSuccessfully = value.TryFormat(buffer, out int charsWritten, "O", CultureInfo.InvariantCulture); Debug.Assert(formattedSuccessfully && charsWritten == FormatLength); writer.WriteStringValue(buffer); @@ -65,7 +69,11 @@ public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializer internal override void WriteAsPropertyNameCore(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options, bool isWritingExtensionDataProperty) { +#if NET8_0_OR_GREATER + Span buffer = stackalloc byte[FormatLength]; +#else Span buffer = stackalloc char[FormatLength]; +#endif bool formattedSuccessfully = value.TryFormat(buffer, out int charsWritten, "O", CultureInfo.InvariantCulture); Debug.Assert(formattedSuccessfully && charsWritten == FormatLength); writer.WritePropertyName(buffer); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverterFactory.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverterFactory.cs index b23623fcfb86a9..ed49845dcfb70b 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverterFactory.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/EnumConverterFactory.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.Text.Json.Serialization.Converters @@ -18,7 +19,10 @@ public override bool CanConvert(Type type) } public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options) - => Create(type, EnumConverterOptions.AllowNumbers, namingPolicy: null, options); + { + Debug.Assert(CanConvert(type)); + return Create(type, EnumConverterOptions.AllowNumbers, namingPolicy: null, options); + } internal static JsonConverter Create(Type enumType, EnumConverterOptions converterOptions, JsonNamingPolicy? namingPolicy, JsonSerializerOptions options) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/NullableConverterFactory.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/NullableConverterFactory.cs index a674f805731a0e..53aa155ba84374 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/NullableConverterFactory.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/NullableConverterFactory.cs @@ -18,12 +18,10 @@ public override bool CanConvert(Type typeToConvert) public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) { - Debug.Assert(typeToConvert.GetGenericArguments().Length > 0); + Debug.Assert(typeToConvert.IsNullableOfT()); Type valueTypeToConvert = typeToConvert.GetGenericArguments()[0]; - JsonConverter valueConverter = options.GetConverterInternal(valueTypeToConvert); - Debug.Assert(valueConverter != null); // If the value type has an interface or object converter, just return that converter directly. if (!valueConverter.TypeToConvert.IsValueType && valueTypeToConvert.IsValueType) @@ -36,6 +34,7 @@ public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializer public static JsonConverter CreateValueConverter(Type valueTypeToConvert, JsonConverter valueConverter) { + Debug.Assert(valueTypeToConvert.IsValueType && !valueTypeToConvert.IsNullableOfT()); return (JsonConverter)Activator.CreateInstance( GetNullableConverterType(valueTypeToConvert), BindingFlags.Instance | BindingFlags.Public, diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UnsupportedTypeConverterFactory.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UnsupportedTypeConverterFactory.cs index c911b309ab4c4f..698e2c38b1f767 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UnsupportedTypeConverterFactory.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Converters/Value/UnsupportedTypeConverterFactory.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; using System.Reflection; using System.Runtime.Serialization; @@ -25,12 +26,28 @@ public override bool CanConvert(Type type) type == typeof(SerializationInfo) || type == typeof(IntPtr) || type == typeof(UIntPtr) || + // Exclude Memory and ReadOnlyMemory types. + IsMemoryType(type) || // Exclude delegates. typeof(Delegate).IsAssignableFrom(type); + + static bool IsMemoryType(Type type) + { + if (!type.IsGenericType || !type.IsValueType) + { + return false; + } + + Type typeDef = type.GetGenericTypeDefinition(); + return typeDef == typeof(Memory<>) || typeDef == typeof(ReadOnlyMemory<>); + } } public override JsonConverter CreateConverter(Type type, JsonSerializerOptions options) - => CreateUnsupportedConverterForType(type); + { + Debug.Assert(CanConvert(type)); + return CreateUnsupportedConverterForType(type); + } internal static JsonConverter CreateUnsupportedConverterForType(Type type, string? errorMessage = null) { 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 c90ee22ad28569..ed07581ded9af8 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 @@ -85,7 +85,11 @@ public override void Write(Utf8JsonWriter writer, Version? value, JsonSerializer } #if NETCOREAPP +#if NET8_0_OR_GREATER + Span span = stackalloc byte[MaximumVersionLength]; +#else Span span = stackalloc char[MaximumVersionLength]; +#endif bool formattedSuccessfully = value.TryFormat(span, out int charsWritten); Debug.Assert(formattedSuccessfully && charsWritten >= MinimumVersionLength); writer.WriteStringValue(span.Slice(0, charsWritten)); @@ -107,7 +111,11 @@ internal override void WriteAsPropertyNameCore(Utf8JsonWriter writer, Version va } #if NETCOREAPP +#if NET8_0_OR_GREATER + Span span = stackalloc byte[MaximumVersionLength]; +#else Span span = stackalloc char[MaximumVersionLength]; +#endif bool formattedSuccessfully = value.TryFormat(span, out int charsWritten); Debug.Assert(formattedSuccessfully && charsWritten >= MinimumVersionLength); writer.WritePropertyName(span.Slice(0, charsWritten)); diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.cs index c5bda102264d2f..54d256143aff39 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverter.cs @@ -102,7 +102,41 @@ internal virtual JsonTypeInfo CreateJsonTypeInfo(JsonSerializerOptions options) throw new InvalidOperationException(); } - internal abstract JsonConverter CreateCastingConverter(); + internal JsonConverter CreateCastingConverter() + { + Debug.Assert(this is not JsonConverterFactory); + + if (this is JsonConverter conv) + { + return conv; + } + else + { + JsonSerializerOptions.CheckConverterNullabilityIsSameAsPropertyType(this, typeof(TTarget)); + + // Avoid layering casting converters by consulting any source converters directly. + return + SourceConverterForCastingConverter?.CreateCastingConverter() + ?? new CastingConverter(this); + } + } + + /// + /// Tracks whether the JsonConverter<T>.HandleNull property has been overridden by a derived converter. + /// + internal bool UsesDefaultHandleNull { get; private protected set; } + + /// + /// Does the converter want to be called when reading null tokens. + /// When JsonConverter<T>.HandleNull isn't overridden this can still be true for non-nullable structs. + /// + internal bool HandleNullOnRead { get; private protected init; } + + /// + /// Does the converter want to be called for null values. + /// Should always match the precise value of the JsonConverter<T>.HandleNull virtual property. + /// + internal bool HandleNullOnWrite { get; private protected init; } /// /// Set if this converter is itself a casting converter. diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterFactory.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterFactory.cs index 6d492a1462c150..4ac55167cf5aa0 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterFactory.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonConverterFactory.cs @@ -161,11 +161,5 @@ internal sealed override void WriteNumberWithCustomHandlingAsObject(Utf8JsonWrit throw new InvalidOperationException(); } - - internal sealed override JsonConverter CreateCastingConverter() - { - ThrowHelper.ThrowInvalidOperationException_ConverterCanConvertMultipleTypes(typeof(TTarget), this); - return null!; - } } } 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 0b050ff3917104..34265f4ffaa2b3 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 @@ -26,13 +26,14 @@ protected internal JsonConverter() HandleNullOnRead = true; HandleNullOnWrite = true; } - else + else if (UsesDefaultHandleNull) { - // For the HandleNull == false case, either: - // 1) The default values are assigned in this type's virtual HandleNull property - // or - // 2) A converter overrode HandleNull and returned false so HandleNullOnRead and HandleNullOnWrite - // will be their default values of false. + // If the type doesn't support null, allow the converter a chance to modify. + // These semantics are backwards compatible with 3.0. + HandleNullOnRead = default(T) is not null; + + // The framework handles null automatically on writes. + HandleNullOnWrite = false; } } @@ -56,21 +57,6 @@ internal sealed override JsonTypeInfo CreateJsonTypeInfo(JsonSerializerOptions o return new JsonTypeInfo(this, options); } - internal sealed override JsonConverter CreateCastingConverter() - { - if (this is JsonConverter conv) - { - return conv; - } - - JsonSerializerOptions.CheckConverterNullabilityIsSameAsPropertyType(this, typeof(TTarget)); - - // Avoid layering casting converters by consulting any source converters directly. - return - SourceConverterForCastingConverter?.CreateCastingConverter() - ?? new CastingConverter(this, handleNull: HandleNull, handleNullOnRead: HandleNullOnRead, handleNullOnWrite: HandleNullOnWrite); - } - internal override Type? KeyType => null; internal override Type? ElementType => null; @@ -86,31 +72,11 @@ public virtual bool HandleNull { get { - // HandleNull is only called by the framework once during initialization and any - // subsequent calls elsewhere would just re-initialize to the same values (we don't - // track a "hasInitialized" flag since that isn't necessary). - - // If the type doesn't support null, allow the converter a chance to modify. - // These semantics are backwards compatible with 3.0. - HandleNullOnRead = default(T) is not null; - - // The framework handles null automatically on writes. - HandleNullOnWrite = false; - + UsesDefaultHandleNull = true; return false; } } - /// - /// Does the converter want to be called when reading null tokens. - /// - internal bool HandleNullOnRead { get; private protected set; } - - /// - /// Does the converter want to be called for null values. - /// - internal bool HandleNullOnWrite { get; private protected set; } - // This non-generic API is sealed as it just forwards to the generic version. internal sealed override void WriteAsObject(Utf8JsonWriter writer, object? value, JsonSerializerOptions options) { @@ -255,7 +221,7 @@ internal bool TryRead(ref Utf8JsonReader reader, Type typeToConvert, JsonSeriali { // Special case object converters since they don't // require the expensive ReadStack.Push()/Pop() operations. - Debug.Assert(this is ObjectConverter or ObjectConverterSlim); + Debug.Assert(this is ObjectConverter); success = OnTryRead(ref reader, typeToConvert, options, ref state, out value); Debug.Assert(success); isPopulatedValue = false; 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 836eb216ed052e..201fca14143ee0 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 @@ -183,22 +183,7 @@ internal JsonTypeInfo ObjectTypeInfo get { Debug.Assert(IsReadOnly); - return _objectTypeInfo ??= GetObjectTypeInfo(this); - - static JsonTypeInfo GetObjectTypeInfo(JsonSerializerOptions options) - { - JsonTypeInfo? typeInfo = options.GetTypeInfoInternal(JsonTypeInfo.ObjectType, ensureNotNull: null); - if (typeInfo is null) - { - // If the user-supplied resolver does not provide a JsonTypeInfo, - // use a placeholder value to drive root-level boxed value serialization. - var converter = new ObjectConverterSlim(); - typeInfo = new JsonTypeInfo(converter, options); - typeInfo.EnsureConfigured(); - } - - return typeInfo; - } + return _objectTypeInfo ??= GetTypeInfoInternal(JsonTypeInfo.ObjectType); } } 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 680193ece84f3e..9380884e9f7935 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 @@ -9,6 +9,7 @@ using System.Text.Encodings.Web; using System.Text.Json.Nodes; using System.Text.Json.Serialization; +using System.Text.Json.Serialization.Converters; using System.Text.Json.Serialization.Metadata; using System.Threading; @@ -756,7 +757,13 @@ internal void ConfigureForJsonSerializer() private JsonTypeInfo? GetTypeInfoNoCaching(Type type) { - JsonTypeInfo? info = (_effectiveJsonTypeInfoResolver ?? _typeInfoResolver)?.GetTypeInfo(type, this); + IJsonTypeInfoResolver? resolver = _effectiveJsonTypeInfoResolver ?? _typeInfoResolver; + if (resolver is null) + { + return null; + } + + JsonTypeInfo? info = resolver.GetTypeInfo(type, this); if (info != null) { @@ -770,6 +777,18 @@ internal void ConfigureForJsonSerializer() ThrowHelper.ThrowInvalidOperationException_ResolverTypeInfoOptionsNotCompatible(); } } + else + { + Debug.Assert(_effectiveJsonTypeInfoResolver is null, "an effective resolver always returns metadata"); + + if (type == JsonTypeInfo.ObjectType) + { + // If the resolver does not provide a JsonTypeInfo instance, fill + // with the serialization-only converter to enable polymorphic serialization. + var converter = new SlimObjectConverter(resolver); + info = new JsonTypeInfo(converter, this); + } + } return info; } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonStringEnumConverter.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonStringEnumConverter.cs index 8dfe234d8b4567..4210d666812902 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonStringEnumConverter.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonStringEnumConverter.cs @@ -6,6 +6,61 @@ namespace System.Text.Json.Serialization { + /// + /// Converter to convert enums to and from strings. + /// + /// + /// Reading is case insensitive, writing can be customized via a . + /// + /// The enum type that this converter targets. + public class JsonStringEnumConverter : JsonConverterFactory + where TEnum : struct, Enum + { + private readonly JsonNamingPolicy? _namingPolicy; + private readonly EnumConverterOptions _converterOptions; + + /// + /// Constructor. Creates the with the + /// default naming policy and allows integer values. + /// + public JsonStringEnumConverter() : this(namingPolicy: null, allowIntegerValues: true) + { + // An empty constructor is needed for construction via attributes + } + + /// + /// Constructor. + /// + /// + /// Optional naming policy for writing enum values. + /// + /// + /// True to allow undefined enum values. When true, if an enum value isn't + /// defined it will output as a number rather than a string. + /// + public JsonStringEnumConverter(JsonNamingPolicy? namingPolicy = null, bool allowIntegerValues = true) + { + _namingPolicy = namingPolicy; + _converterOptions = allowIntegerValues + ? EnumConverterOptions.AllowNumbers | EnumConverterOptions.AllowStrings + : EnumConverterOptions.AllowStrings; + } + + /// + public override bool CanConvert(Type typeToConvert) => typeToConvert == typeof(TEnum); + + /// + public override JsonConverter? CreateConverter(Type typeToConvert, JsonSerializerOptions options) + { + if (typeToConvert != typeof(TEnum)) + { + ThrowHelper.ThrowArgumentOutOfRangeException_JsonConverterFactory_TypeNotSupported(typeToConvert); + } + + return new EnumConverter(_converterOptions, _namingPolicy, options); + } + } + /// /// Converter to convert enums to and from strings. /// @@ -14,8 +69,7 @@ namespace System.Text.Json.Serialization /// [RequiresDynamicCode( "JsonStringEnumConverter cannot be statically analyzed and requires runtime code generation. " + - "Consider authoring a custom converter that is not a factory to work around the issue. " + - "See https://github.com/dotnet/runtime/issues/73124.")] + "Applications should use the generic JsonStringEnumConverter instead.")] public class JsonStringEnumConverter : JsonConverterFactory { private readonly JsonNamingPolicy? _namingPolicy; @@ -25,8 +79,7 @@ public class JsonStringEnumConverter : JsonConverterFactory /// Constructor. Creates the with the /// default naming policy and allows integer values. /// - public JsonStringEnumConverter() - : this(namingPolicy: null, allowIntegerValues: true) + public JsonStringEnumConverter() : this(namingPolicy: null, allowIntegerValues: true) { // An empty constructor is needed for construction via attributes } @@ -56,7 +109,14 @@ public sealed override bool CanConvert(Type typeToConvert) } /// - public sealed override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) => - EnumConverterFactory.Create(typeToConvert, _converterOptions, _namingPolicy, options); + public sealed override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options) + { + if (!typeToConvert.IsEnum) + { + ThrowHelper.ThrowArgumentOutOfRangeException_JsonConverterFactory_TypeNotSupported(typeToConvert); + } + + return EnumConverterFactory.Create(typeToConvert, _converterOptions, _namingPolicy, options); + } } } 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 75b81cf6f0768b..8edd9878660a2d 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 @@ -102,7 +102,7 @@ private static void PopulateProperties(JsonTypeInfo typeInfo) if (state.IsPropertyOrderSpecified) { - typeInfo.SortProperties(); + typeInfo.PropertyList.SortProperties(); } } @@ -210,7 +210,7 @@ private static void AddMember( } Debug.Assert(jsonPropertyInfo.Name != null); - typeInfo.AddProperty(jsonPropertyInfo, ref state); + typeInfo.PropertyList.AddPropertyWithConflictResolution(jsonPropertyInfo, ref state); } [RequiresUnreferencedCode(JsonSerializer.SerializationUnreferencedCodeMessage)] 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 d2cbc240b1b69c..6377bab463acd6 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 @@ -154,7 +154,7 @@ public static partial class JsonMetadataServices /// Returns a instance that converts values. /// /// This API is for use by the output of the System.Text.Json source generator and should not be called directly. - public static JsonConverter ObjectConverter => s_objectConverter ??= new ObjectConverter(); + public static JsonConverter ObjectConverter => s_objectConverter ??= new DefaultObjectConverter(); private static JsonConverter? s_objectConverter; /// diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Helpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Helpers.cs index 381f3c407a59bc..74012964a2b5ea 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Helpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/Metadata/JsonMetadataServices.Helpers.cs @@ -14,7 +14,7 @@ public static partial class JsonMetadataServices /// private static JsonTypeInfo CreateCore(JsonConverter converter, JsonSerializerOptions options) { - JsonTypeInfo typeInfo = new JsonTypeInfo(converter, options); + var typeInfo = new JsonTypeInfo(converter, options); typeInfo.PopulatePolymorphismMetadata(); typeInfo.MapInterfaceTypesToCallbacks(); @@ -29,7 +29,7 @@ private static JsonTypeInfo CreateCore(JsonConverter converter, JsonSerial private static JsonTypeInfo CreateCore(JsonSerializerOptions options, JsonObjectInfoValues objectInfo) { JsonConverter converter = GetConverter(objectInfo); - JsonTypeInfo typeInfo = new JsonTypeInfo(converter, options); + var typeInfo = new JsonTypeInfo(converter, options); if (objectInfo.ObjectWithParameterizedConstructorCreator != null) { typeInfo.CreateObjectWithArgs = objectInfo.ObjectWithParameterizedConstructorCreator; @@ -41,7 +41,15 @@ private static JsonTypeInfo CreateCore(JsonSerializerOptions options, Json typeInfo.CreateObjectForExtensionDataProperty = ((JsonTypeInfo)typeInfo).CreateObject; } - PopulateProperties(typeInfo, objectInfo.PropertyMetadataInitializer); + if (objectInfo.PropertyMetadataInitializer != null) + { + typeInfo.SourceGenDelayedPropertyInitializer = objectInfo.PropertyMetadataInitializer; + } + else + { + typeInfo.PropertyMetadataSerializationNotSupported = true; + } + typeInfo.SerializeHandler = objectInfo.SerializeHandler; typeInfo.NumberHandling = objectInfo.NumberHandling; typeInfo.PopulatePolymorphismMetadata(); @@ -62,15 +70,16 @@ private static JsonTypeInfo CreateCore( object? createObjectWithArgs = null, object? addFunc = null) { + if (collectionInfo is null) + { + ThrowHelper.ThrowArgumentNullException(nameof(collectionInfo)); + } + converter = collectionInfo.SerializeHandler != null ? new JsonMetadataServicesConverter(converter) : converter; JsonTypeInfo typeInfo = new JsonTypeInfo(converter, options); - if (collectionInfo is null) - { - ThrowHelper.ThrowArgumentNullException(nameof(collectionInfo)); - } typeInfo.KeyTypeInfo = collectionInfo.KeyInfo; typeInfo.ElementTypeInfo = collectionInfo.ElementInfo; @@ -116,28 +125,15 @@ private static void PopulateParameterInfoValues(JsonTypeInfo typeInfo, Func? propInitFunc) + internal static void PopulateProperties(JsonTypeInfo typeInfo, JsonTypeInfo.JsonPropertyInfoList propertyList, Func propInitFunc) { Debug.Assert(typeInfo.Kind is JsonTypeInfoKind.Object); - Debug.Assert(!typeInfo.IsReadOnly); - - JsonSerializerContext? context = (typeInfo.OriginatingResolver ?? typeInfo.Options.TypeInfoResolver) as JsonSerializerContext; - if (propInitFunc?.Invoke(context!) is not JsonPropertyInfo[] properties) - { - if (typeInfo.Type == JsonTypeInfo.ObjectType) - { - return; - } + Debug.Assert(!typeInfo.IsConfigured); + Debug.Assert(typeInfo.Type != JsonTypeInfo.ObjectType); + Debug.Assert(typeInfo.Converter.ElementType is null); - if (typeInfo.Converter.ElementType != null) - { - // Nullable<> or F# optional converter strategy is set to element strategy - return; - } - - typeInfo.PropertyMetadataSerializationNotSupported = true; - return; - } + JsonSerializerContext? context = typeInfo.Options.TypeInfoResolver as JsonSerializerContext; + JsonPropertyInfo[] properties = propInitFunc(context!); // TODO update the source generator so that all property // hierarchy resolution is happening at compile time. @@ -161,7 +157,7 @@ private static void PopulateProperties(JsonTypeInfo typeInfo, Func? OnDeserialized /// It is required that added entries are unique up to , /// however this will only be validated on serialization, once the metadata instance gets locked for further modification. /// - public IList Properties => _properties ??= new(this); - private JsonPropertyInfoList? _properties; + public IList Properties => PropertyList; - internal void SortProperties() + internal JsonPropertyInfoList PropertyList { - Debug.Assert(!IsConfigured); - Debug.Assert(_properties != null && _properties.Count > 0); + get + { + return _properties ?? CreatePropertyList(); + JsonPropertyInfoList CreatePropertyList() + { + var list = new JsonPropertyInfoList(this); + if (_sourceGenDelayedPropertyInitializer is { } propInit) + { + // .NET 6 source gen backward compatibility -- ensure that the + // property initializer delegate is invoked lazily. + JsonMetadataServices.PopulateProperties(this, list, propInit); + } - _properties.SortProperties(); - PropertyCache?.List.StableSortByKey(static propInfo => propInfo.Value.Order); + JsonPropertyInfoList? result = Interlocked.CompareExchange(ref _properties, list, null); + _sourceGenDelayedPropertyInitializer = null; + return result ?? list; + } + } } + /// + /// Stores the .NET 6-style property initialization delegate for delayed evaluation. + /// + internal Func? SourceGenDelayedPropertyInitializer + { + get => _sourceGenDelayedPropertyInitializer; + set + { + Debug.Assert(!IsReadOnly); + Debug.Assert(_properties is null, "must not be set if a property list has been initialized."); + _sourceGenDelayedPropertyInitializer = value; + } + } + + private Func? _sourceGenDelayedPropertyInitializer; + private JsonPropertyInfoList? _properties; + /// /// Gets or sets a configuration object specifying polymorphism metadata. /// @@ -956,76 +985,6 @@ public JsonPropertyInfo CreateJsonPropertyInfo(Type propertyType, string name) internal abstract ValueTask DeserializeAsObjectAsync(Stream utf8Json, CancellationToken cancellationToken); internal abstract object? DeserializeAsObject(Stream utf8Json); - /// - /// Used by the built-in resolvers to add property metadata applying conflict resolution. - /// - internal void AddProperty(JsonPropertyInfo jsonPropertyInfo, ref PropertyHierarchyResolutionState state) - { - Debug.Assert(jsonPropertyInfo.MemberName != null, "MemberName can be null in custom JsonPropertyInfo instances and should never be passed in this method"); - string memberName = jsonPropertyInfo.MemberName; - - JsonPropertyInfoList properties = _properties ??= new(this); - - if (state.AddedProperties.TryAdd(jsonPropertyInfo.Name, (jsonPropertyInfo, properties.Count))) - { - properties.Add(jsonPropertyInfo); - state.IsPropertyOrderSpecified |= jsonPropertyInfo.Order != 0; - } - else - { - // The JsonPropertyNameAttribute or naming policy resulted in a collision. - (JsonPropertyInfo other, int index) = state.AddedProperties[jsonPropertyInfo.Name]; - - if (other.IsIgnored) - { - // Overwrite previously cached property since it has [JsonIgnore]. - state.AddedProperties[jsonPropertyInfo.Name] = (jsonPropertyInfo, index); - properties[index] = jsonPropertyInfo; - state.IsPropertyOrderSpecified |= jsonPropertyInfo.Order != 0; - } - else - { - bool ignoreCurrentProperty; - - if (!Type.IsInterface) - { - ignoreCurrentProperty = - // Does the current property have `JsonIgnoreAttribute`? - jsonPropertyInfo.IsIgnored || - // Is the current property hidden by the previously cached property - // (with `new` keyword, or by overriding)? - other.MemberName == memberName || - // Was a property with the same CLR name ignored? That property hid the current property, - // thus, if it was ignored, the current property should be ignored too. - state.IgnoredProperties?.ContainsKey(memberName) == true; - } - else - { - // Unlike classes, interface hierarchies reject all naming conflicts for non-ignored properties. - // Conflicts like this are possible in two cases: - // 1. Diamond ambiguity in property names, or - // 2. Linear interface hierarchies that use properties with DIMs. - // - // Diamond ambiguities are not supported. Assuming there is demand, we might consider - // adding support for DIMs in the future, however that would require adding more APIs - // for the case of source gen. - - ignoreCurrentProperty = jsonPropertyInfo.IsIgnored; - } - - if (!ignoreCurrentProperty) - { - ThrowHelper.ThrowInvalidOperationException_SerializerPropertyNameConflict(Type, jsonPropertyInfo.Name); - } - } - } - - if (jsonPropertyInfo.IsIgnored) - { - (state.IgnoredProperties ??= new()).Add(memberName, jsonPropertyInfo); - } - } - internal ref struct PropertyHierarchyResolutionState { public PropertyHierarchyResolutionState() { } @@ -1076,9 +1035,9 @@ internal void ConfigureProperties() Debug.Assert(PropertyCache is null); Debug.Assert(ExtensionDataProperty is null); - IList properties = (IList?)_properties ?? Array.Empty(); - + JsonPropertyInfoList properties = PropertyList; JsonPropertyDictionary propertyCache = CreatePropertyCache(capacity: properties.Count); + int numberOfRequiredProperties = 0; bool arePropertiesSorted = true; int previousPropertyOrder = int.MinValue; @@ -1123,15 +1082,16 @@ internal void ConfigureProperties() property.Configure(); } - NumberOfRequiredProperties = numberOfRequiredProperties; - PropertyCache = propertyCache; - if (!arePropertiesSorted) { // Properties have been configured by the user and require sorting. - SortProperties(); + properties.SortProperties(); + propertyCache.List.StableSortByKey(static propInfo => propInfo.Value.Order); } + NumberOfRequiredProperties = numberOfRequiredProperties; + PropertyCache = propertyCache; + // Override global UnmappedMemberHandling configuration // if type specifies an extension data property. EffectiveUnmappedMemberHandling = UnmappedMemberHandling ?? @@ -1206,6 +1166,7 @@ internal void ConfigureConstructorParameters() ParameterCount = jsonParameters.Length; ParameterCache = parameterCache; + ParameterInfoValues = null; } internal static void ValidateType(Type type) @@ -1326,7 +1287,7 @@ private static JsonTypeInfoKind GetTypeInfoKind(Type type, JsonConverter convert if (type == typeof(object) && converter.CanBePolymorphic) { // System.Object is polymorphic and will not respect Properties - Debug.Assert(converter is ObjectConverter or ObjectConverterSlim); + Debug.Assert(converter is ObjectConverter); return JsonTypeInfoKind.None; } @@ -1346,7 +1307,7 @@ private static JsonTypeInfoKind GetTypeInfoKind(Type type, JsonConverter convert } } - private sealed class JsonPropertyInfoList : ConfigurationList + internal sealed class JsonPropertyInfoList : ConfigurationList { private readonly JsonTypeInfo _jsonTypeInfo; @@ -1355,10 +1316,13 @@ public JsonPropertyInfoList(JsonTypeInfo jsonTypeInfo) _jsonTypeInfo = jsonTypeInfo; } - public override bool IsReadOnly => _jsonTypeInfo.IsReadOnly || _jsonTypeInfo.Kind != JsonTypeInfoKind.Object; + public override bool IsReadOnly => _jsonTypeInfo._properties == this && _jsonTypeInfo.IsReadOnly || _jsonTypeInfo.Kind != JsonTypeInfoKind.Object; protected override void OnCollectionModifying() { - _jsonTypeInfo.VerifyMutable(); + if (_jsonTypeInfo._properties == this) + { + _jsonTypeInfo.VerifyMutable(); + } if (_jsonTypeInfo.Kind != JsonTypeInfoKind.Object) { @@ -1372,7 +1336,79 @@ protected override void ValidateAddedValue(JsonPropertyInfo item) } public void SortProperties() - => _list.StableSortByKey(static propInfo => propInfo.Order); + { + _list.StableSortByKey(static propInfo => propInfo.Order); + } + + /// + /// Used by the built-in resolvers to add property metadata applying conflict resolution. + /// + public void AddPropertyWithConflictResolution(JsonPropertyInfo jsonPropertyInfo, ref PropertyHierarchyResolutionState state) + { + Debug.Assert(!_jsonTypeInfo.IsConfigured); + Debug.Assert(jsonPropertyInfo.MemberName != null, "MemberName can be null in custom JsonPropertyInfo instances and should never be passed in this method"); + string memberName = jsonPropertyInfo.MemberName; + + if (state.AddedProperties.TryAdd(jsonPropertyInfo.Name, (jsonPropertyInfo, Count))) + { + Add(jsonPropertyInfo); + state.IsPropertyOrderSpecified |= jsonPropertyInfo.Order != 0; + } + else + { + // The JsonPropertyNameAttribute or naming policy resulted in a collision. + (JsonPropertyInfo other, int index) = state.AddedProperties[jsonPropertyInfo.Name]; + + if (other.IsIgnored) + { + // Overwrite previously cached property since it has [JsonIgnore]. + state.AddedProperties[jsonPropertyInfo.Name] = (jsonPropertyInfo, index); + this[index] = jsonPropertyInfo; + state.IsPropertyOrderSpecified |= jsonPropertyInfo.Order != 0; + } + else + { + bool ignoreCurrentProperty; + + if (!_jsonTypeInfo.Type.IsInterface) + { + ignoreCurrentProperty = + // Does the current property have `JsonIgnoreAttribute`? + jsonPropertyInfo.IsIgnored || + // Is the current property hidden by the previously cached property + // (with `new` keyword, or by overriding)? + other.MemberName == memberName || + // Was a property with the same CLR name ignored? That property hid the current property, + // thus, if it was ignored, the current property should be ignored too. + state.IgnoredProperties?.ContainsKey(memberName) == true; + } + else + { + // Unlike classes, interface hierarchies reject all naming conflicts for non-ignored properties. + // Conflicts like this are possible in two cases: + // 1. Diamond ambiguity in property names, or + // 2. Linear interface hierarchies that use properties with DIMs. + // + // Diamond ambiguities are not supported. Assuming there is demand, we might consider + // adding support for DIMs in the future, however that would require adding more APIs + // for the case of source gen. + + ignoreCurrentProperty = jsonPropertyInfo.IsIgnored; + } + + if (!ignoreCurrentProperty) + { + ThrowHelper.ThrowInvalidOperationException_SerializerPropertyNameConflict(_jsonTypeInfo.Type, jsonPropertyInfo.Name); + } + } + } + + if (jsonPropertyInfo.IsIgnored) + { + state.IgnoredProperties ??= new(); + state.IgnoredProperties[memberName] = jsonPropertyInfo; + } + } } [DebuggerBrowsable(DebuggerBrowsableState.Never)] 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 90b44b1b6f4d6c..d916334c1925a3 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 @@ -149,15 +149,16 @@ rootValue is not null && // Note that pending tasks are always awaited, even if an exception has been thrown or the cancellation token has fired. if (state.PendingTask is not null) { + // Exceptions should only be propagated by the resuming converter +#if NET8_0_OR_GREATER + await state.PendingTask.ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing); +#else try { await state.PendingTask.ConfigureAwait(false); } - catch - { - // Exceptions should only be propagated by the resuming converter - // TODO https://github.com/dotnet/runtime/issues/22144 - } + catch { } +#endif } // Dispose any pending async disposables (currently these can only be completed IAsyncEnumerators). 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 417ed4c520b988..b2e96d71c3982f 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 @@ -35,6 +35,12 @@ public static void ThrowArgumentOutOfRangeException_ArrayIndexNegative(string pa throw new ArgumentOutOfRangeException(paramName, SR.ArrayIndexNegative); } + [DoesNotReturn] + public static void ThrowArgumentOutOfRangeException_JsonConverterFactory_TypeNotSupported(Type typeToConvert) + { + throw new ArgumentOutOfRangeException(nameof(typeToConvert), SR.Format(SR.SerializerConverterFactoryInvalidArgument, typeToConvert.FullName)); + } + [DoesNotReturn] public static void ThrowArgumentException_ArrayTooSmall(string paramName) { diff --git a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.AsyncEnumerable.cs b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.AsyncEnumerable.cs index 0ae7c05046fd5d..7b87042daab865 100644 --- a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.AsyncEnumerable.cs +++ b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.AsyncEnumerable.cs @@ -23,12 +23,10 @@ public async Task WriteRootLevelAsyncEnumerable(IEnumerable return; } - JsonSerializerOptions options = new JsonSerializerOptions - { - DefaultBufferSize = bufferSize - }; + JsonSerializerOptions options = Serializer.CreateOptions(makeReadOnly: false); + options.DefaultBufferSize = bufferSize; - string expectedJson = JsonSerializer.Serialize(source); + string expectedJson = JsonSerializer.Serialize(source, options); using var stream = new Utf8MemoryStream(); var asyncEnumerable = new MockedAsyncEnumerable(source, delayInterval); @@ -48,37 +46,10 @@ public async Task WriteNestedAsyncEnumerable(IEnumerable sou return; } - JsonSerializerOptions options = new JsonSerializerOptions - { - DefaultBufferSize = bufferSize - }; + JsonSerializerOptions options = Serializer.CreateOptions(makeReadOnly: false); + options.DefaultBufferSize = bufferSize; - string expectedJson = JsonSerializer.Serialize(new { Data = source }); - - using var stream = new Utf8MemoryStream(); - var asyncEnumerable = new MockedAsyncEnumerable(source, delayInterval); - await StreamingSerializer.SerializeWrapper(stream, new AsyncEnumerableDto { Data = asyncEnumerable }, options); - - JsonTestHelper.AssertJsonEqual(expectedJson, stream.AsString()); - Assert.Equal(1, asyncEnumerable.TotalCreatedEnumerators); - Assert.Equal(1, asyncEnumerable.TotalDisposedEnumerators); - } - - [Theory] - [MemberData(nameof(GetAsyncEnumerableSources))] - public async Task WriteNestedAsyncEnumerable_DTO(IEnumerable source, int delayInterval, int bufferSize) - { - if (StreamingSerializer?.IsAsyncSerializer != true) - { - return; - } - - JsonSerializerOptions options = new JsonSerializerOptions - { - DefaultBufferSize = bufferSize - }; - - string expectedJson = JsonSerializer.Serialize(new { Data = source }); + string expectedJson = JsonSerializer.Serialize(new EnumerableDto { Data = source }, options); using var stream = new Utf8MemoryStream(); var asyncEnumerable = new MockedAsyncEnumerable(source, delayInterval); @@ -100,11 +71,9 @@ public async Task WriteNestedAsyncEnumerable_Nullable(IEnumerable, bool)?>((source, false), options); @@ -164,11 +133,22 @@ await Assert.ThrowsAsync(async () => Assert.Equal(1, longRunningEnumerable.TotalDisposedEnumerators); } + public class EnumerableDto + { + public IEnumerable Data { get; set; } + } + public class AsyncEnumerableDto { public IAsyncEnumerable Data { get; set; } } + public class EnumerableDtoWithTwoProperties + { + public IEnumerable Data1 { get; set; } + public IEnumerable Data2 { get; set; } + } + public class AsyncEnumerableDtoWithTwoProperties { public IAsyncEnumerable Data1 { get; set; } @@ -184,12 +164,10 @@ public async Task WriteSequentialNestedAsyncEnumerables(IEnumerable { Data1 = source, Data2 = source }, options); using var stream = new Utf8MemoryStream(); var asyncEnumerable = new MockedAsyncEnumerable(source, delayInterval); @@ -209,13 +187,11 @@ public async Task WriteAsyncEnumerableOfAsyncEnumerables(IEnumerable(source, delayInterval); var outerAsyncEnumerable = diff --git a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Generic.Read.cs b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Generic.Read.cs index 98ea68cbdd7d35..a1b9b76f003ceb 100644 --- a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Generic.Read.cs +++ b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Generic.Read.cs @@ -617,20 +617,19 @@ public async Task ReadNullableGenericStructISetWithNullJson() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50721", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] public async Task ReadISetTOfHashSetT() { ISet> result = await Serializer.DeserializeWrapper>>(@"[[1,2],[3,4]]"); if (result.First().Contains(1)) { - Assert.Equal(new HashSet { 1, 2 }, result.First()); - Assert.Equal(new HashSet { 3, 4 }, result.Last()); + AssertExtensions.Equal(new HashSet { 1, 2 }, result.First()); + AssertExtensions.Equal(new HashSet { 3, 4 }, result.Last()); } else { - Assert.Equal(new HashSet { 3, 4 }, result.First()); - Assert.Equal(new HashSet { 1, 2 }, result.Last()); + AssertExtensions.Equal(new HashSet { 3, 4 }, result.First()); + AssertExtensions.Equal(new HashSet { 1, 2 }, result.Last()); } } diff --git a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Generic.Write.cs b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Generic.Write.cs index 935ec9e6c00504..a6131347de3cdf 100644 --- a/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Generic.Write.cs +++ b/src/libraries/System.Text.Json/tests/Common/CollectionTests/CollectionTests.Generic.Write.cs @@ -384,7 +384,6 @@ public async Task GenericStructISetWrapperT() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50721", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] public async Task WriteISetTOfISetT() { ISet> input = new HashSet> @@ -433,7 +432,6 @@ public async Task WriteISetTOfISetT() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50721", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] public async Task WriteISetTOfHashSetT() { ISet> input = new HashSet> @@ -449,13 +447,13 @@ public async Task WriteISetTOfHashSetT() if (input.First().Contains(1)) { - Assert.Equal(new HashSet { 1, 2 }, input.First()); - Assert.Equal(new HashSet { 3, 4 }, input.Last()); + AssertExtensions.Equal(new HashSet { 1, 2 }, input.First()); + AssertExtensions.Equal(new HashSet { 3, 4 }, input.Last()); } else { - Assert.Equal(new HashSet { 3, 4 }, input.First()); - Assert.Equal(new HashSet { 1, 2 }, input.Last()); + AssertExtensions.Equal(new HashSet { 3, 4 }, input.First()); + AssertExtensions.Equal(new HashSet { 1, 2 }, input.Last()); } } @@ -649,13 +647,13 @@ public async Task WriteHashSetTOfHashSetT() if (input.First().Contains(1)) { - Assert.Equal(new HashSet { 1, 2 }, input.First()); - Assert.Equal(new HashSet { 3, 4 }, input.Last()); + AssertExtensions.Equal(new HashSet { 1, 2 }, input.First()); + AssertExtensions.Equal(new HashSet { 3, 4 }, input.Last()); } else { - Assert.Equal(new HashSet { 3, 4 }, input.First()); - Assert.Equal(new HashSet { 1, 2 }, input.Last()); + AssertExtensions.Equal(new HashSet { 3, 4 }, input.First()); + AssertExtensions.Equal(new HashSet { 1, 2 }, input.Last()); } GenericHashSetWrapper input2 = new GenericHashSetWrapper(new List @@ -696,7 +694,6 @@ public async Task WriteHashSetTOfArray() } [Fact] - [ActiveIssue("https://github.com/dotnet/runtime/issues/50721", typeof(PlatformDetection), nameof(PlatformDetection.IsBuiltWithAggressiveTrimming), nameof(PlatformDetection.IsBrowser))] public async Task WriteArrayOfHashSetT() { HashSet[] input = new HashSet[2]; @@ -707,8 +704,8 @@ public async Task WriteArrayOfHashSetT() // Because order isn't guaranteed, roundtrip data to ensure write was accurate. input = await Serializer.DeserializeWrapper[]>(json); - Assert.Equal(new HashSet { 1, 2 }, input.First()); - Assert.Equal(new HashSet { 3, 4 }, input.Last()); + AssertExtensions.Equal(new HashSet { 1, 2 }, input.First()); + AssertExtensions.Equal(new HashSet { 3, 4 }, input.Last()); } [Fact] diff --git a/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Cache.cs b/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Cache.cs index 2f121926b4cc9b..de5ab8b1477040 100644 --- a/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Cache.cs +++ b/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.Cache.cs @@ -61,7 +61,7 @@ async Task SerializeObject(Type type, JsonSerializerOptions options) async Task RunTestAsync(Type type) { // Use local options to avoid obtaining already cached metadata from the default options. - var options = new JsonSerializerOptions(); + JsonSerializerOptions options = Serializer.CreateOptions(); const int ThreadCount = 8; const int ConcurrentTestsCount = 4; @@ -90,7 +90,7 @@ async Task RunTestAsync(Type type) public async Task PropertyCacheWithMinInputsFirst() { // Use local options to avoid obtaining already cached metadata from the default options. - var options = new JsonSerializerOptions(); + JsonSerializerOptions options = Serializer.CreateOptions(); string json = "{}"; await Serializer.DeserializeWrapper(json, options); @@ -107,7 +107,7 @@ public async Task PropertyCacheWithMinInputsFirst() public async Task PropertyCacheWithMinInputsLast() { // Use local options to avoid obtaining already cached metadata from the default options. - var options = new JsonSerializerOptions(); + JsonSerializerOptions options = Serializer.CreateOptions(); ObjWCtorMixedParams testObj = ObjWCtorMixedParams.GetInstance(); testObj.Verify(); diff --git a/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.ParameterMatching.cs b/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.ParameterMatching.cs index 7770389075b6e6..b06f0ad9bbae16 100644 --- a/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.ParameterMatching.cs +++ b/src/libraries/System.Text.Json/tests/Common/ConstructorTests/ConstructorTests.ParameterMatching.cs @@ -1049,23 +1049,24 @@ public async Task InvalidJsonFails() await Assert.ThrowsAsync(() => Serializer.DeserializeWrapper("{true")); } +#if !BUILDING_SOURCE_GENERATOR_TESTS // Anonymous types not supported in source gen [Fact] - public void AnonymousObject() + public async Task AnonymousObject() { var obj = new { Prop = 5 }; Type objType = obj.GetType(); // 'Prop' property binds with a ctor arg called 'Prop'. - object newObj = JsonSerializer.Deserialize("{}", objType); + object newObj = await Serializer.DeserializeWrapper("{}", objType); Assert.Equal(0, objType.GetProperty("Prop").GetValue(newObj)); - newObj = JsonSerializer.Deserialize(@"{""Prop"":5}", objType); + newObj = await Serializer.DeserializeWrapper(@"{""Prop"":5}", objType); Assert.Equal(5, objType.GetProperty("Prop").GetValue(newObj)); } [Fact] - public void AnonymousObject_NamingPolicy() + public async Task AnonymousObject_NamingPolicy() { const string Json = @"{""prop"":5}"; @@ -1074,7 +1075,7 @@ public void AnonymousObject_NamingPolicy() // 'Prop' property binds with a ctor arg called 'Prop'. - object newObj = JsonSerializer.Deserialize(Json, objType); + object newObj = await Serializer.DeserializeWrapper(Json, objType); // Verify no match if no naming policy Assert.Equal(0, objType.GetProperty("Prop").GetValue(newObj)); @@ -1083,10 +1084,11 @@ public void AnonymousObject_NamingPolicy() PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; - newObj = JsonSerializer.Deserialize(Json, objType, options); + newObj = await Serializer.DeserializeWrapper(Json, objType, options); // Verify match with naming policy Assert.Equal(5, objType.GetProperty("Prop").GetValue(newObj)); } +#endif public record MyRecord(int Prop); @@ -1329,29 +1331,29 @@ public ClassWithIgnoredSameType(ClassWithIgnoredSameType prop) { } } [Fact] - public void StructWithPropertyInit_DeseralizeEmptyObject() + public async Task StructWithPropertyInit_DeseralizeEmptyObject() { string json = @"{}"; - var obj = JsonSerializer.Deserialize(json); + var obj = await Serializer.DeserializeWrapper(json); Assert.Equal(42, obj.A); Assert.Equal(0, obj.B); } [Fact] - public void StructWithPropertyInit_OverrideInitedProperty() + public async Task StructWithPropertyInit_OverrideInitedProperty() { string json = @"{""A"":43}"; - var obj = JsonSerializer.Deserialize(json); + var obj = await Serializer.DeserializeWrapper(json); Assert.Equal(43, obj.A); Assert.Equal(0, obj.B); json = @"{""A"":0,""B"":44}"; - obj = JsonSerializer.Deserialize(json); + obj = await Serializer.DeserializeWrapper(json); Assert.Equal(0, obj.A); Assert.Equal(44, obj.B); json = @"{""B"":45}"; - obj = JsonSerializer.Deserialize(json); + obj = await Serializer.DeserializeWrapper(json); Assert.Equal(42, obj.A); // JSON doesn't set A property so it's expected to be 42 Assert.Equal(45, obj.B); } @@ -1364,10 +1366,10 @@ public struct StructWithPropertyInit } [Fact] - public void StructWithFieldInit_DeseralizeEmptyObject() + public async Task StructWithFieldInit_DeseralizeEmptyObject() { string json = @"{}"; - var obj = JsonSerializer.Deserialize(json); + var obj = await Serializer.DeserializeWrapper(json); Assert.Equal(0, obj.A); Assert.Equal(42, obj.B); } @@ -1380,10 +1382,10 @@ public struct StructWithFieldInit } [Fact] - public void StructWithExplicitParameterlessCtor_DeseralizeEmptyObject() + public async Task StructWithExplicitParameterlessCtor_DeseralizeEmptyObject() { string json = @"{}"; - var obj = JsonSerializer.Deserialize(json); + var obj = await Serializer.DeserializeWrapper(json); Assert.Equal(42, obj.A); } @@ -1431,18 +1433,17 @@ public async Task TestClassWithDefaultCtorParams() JsonTestHelper.AssertJsonEqual(json, await Serializer.SerializeWrapper(obj)); } -#if FIXED // https://github.com/dotnet/roslyn/issues/66900 [Fact] public async Task TestClassWithManyConstructorParameters() { ClassWithManyConstructorParameters value = ClassWithManyConstructorParameters.Create(); - string json = JsonSerializer.Serialize(value); + string json = await Serializer.SerializeWrapper(value); ClassWithManyConstructorParameters result = await Serializer.DeserializeWrapper(json); Assert.Equal(value, result); // Type is C# record that implements structural equality. } -#endif + public class ClassWithDefaultCtorParams { public Point_2D_Struct_WithAttribute Struct { get; } @@ -1574,7 +1575,7 @@ public TypeWithEnumParameters(MyEnum value = MyEnum.One, MyEnum? nullableValue = } } - [JsonConverter(typeof(JsonStringEnumConverter))] + [JsonConverter(typeof(JsonStringEnumConverter))] public enum MyEnum { One = 1, @@ -1600,5 +1601,32 @@ public class ClassWithIgnoredPropertyDefaultParam public ClassWithIgnoredPropertyDefaultParam(int x, int y = 5) => (X, Y) = (x, y); } + + [Fact] + public async Task TestClassWithCustomConverterOnCtorParameter_ShouldPassCorrectTypeToConvertParameter() + { + ClassWithCustomConverterOnCtorParameter result = await Serializer.DeserializeWrapper("""{"Id":"id"}"""); + Assert.Equal("id", result.Id); + } + + public class ClassWithCustomConverterOnCtorParameter + { + public ClassWithCustomConverterOnCtorParameter(string id) => Id = id; + + [JsonConverter(typeof(CustomCtorParameterConverter))] + public string Id { get; } + } + + public class CustomCtorParameterConverter : JsonConverter + { + public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + Assert.Equal(typeof(string), typeToConvert); + return reader.GetString(); + } + + public override void Write(Utf8JsonWriter writer, string value, JsonSerializerOptions options) + => writer.WriteStringValue(value); + } } } diff --git a/src/libraries/System.Text.Json/tests/Common/ExtensionDataTests.cs b/src/libraries/System.Text.Json/tests/Common/ExtensionDataTests.cs index d3a6548226d71b..5801c31e41085e 100644 --- a/src/libraries/System.Text.Json/tests/Common/ExtensionDataTests.cs +++ b/src/libraries/System.Text.Json/tests/Common/ExtensionDataTests.cs @@ -1,10 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Reflection; using System.Text.Encodings.Web; using System.Text.Json.Nodes; using System.Threading.Tasks; @@ -428,104 +428,93 @@ public override void Write(Utf8JsonWriter writer, CustomOverflowDictionary), typeof(DictionaryOverflowConverter))] - [InlineData(typeof(Dictionary), typeof(JsonElementOverflowConverter))] - [InlineData(typeof(CustomOverflowDictionary), typeof(CustomObjectDictionaryOverflowConverter))] - [InlineData(typeof(CustomOverflowDictionary), typeof(CustomJsonElementDictionaryOverflowConverter))] - public void ExtensionProperty_SupportsWritingToCustomSerializerWithOptions(Type overflowType, Type converterType) - { - typeof(ExtensionDataTests) - .GetMethod(nameof(ExtensionProperty_SupportsWritingToCustomSerializerWithOptionsInternal), BindingFlags.Static | BindingFlags.NonPublic) - .MakeGenericMethod(overflowType, converterType) - .Invoke(null, null); - } - - private static void ExtensionProperty_SupportsWritingToCustomSerializerWithOptionsInternal() - where TDictionary : new() - where TConverter : JsonConverter, new() + [MemberData(nameof(GetCustomOverflowConverters))] + public async Task ExtensionProperty_SupportsWritingToCustomSerializerWithOptions(JsonConverter dictionaryConverter) + where TDictionary : IDictionary, new() { var root = new ClassWithExtensionData() { Overflow = new TDictionary() }; - var options = new JsonSerializerOptions(); - options.Converters.Add(new TConverter()); + var options = Serializer.CreateOptions(makeReadOnly: false); + options.Converters.Add(dictionaryConverter); - string json = JsonSerializer.Serialize(root, options); + string json = await Serializer.SerializeWrapper(root, options); Assert.Equal(@"{""MyCustomOverflowWrite"":""OverflowValueWrite""}", json); } - private interface IClassWithOverflow + public interface IClassWithOverflow { - public T Overflow { get; set; } + public IDictionary GetOverflow(); } - public class ClassWithExtensionDataWithAttributedConverter : IClassWithOverflow> + public class ClassWithExtensionDataWithAttributedConverter : IClassWithOverflow { [JsonExtensionData] [JsonConverter(typeof(DictionaryOverflowConverter))] public Dictionary Overflow { get; set; } + + public IDictionary GetOverflow() => Overflow; } - public class ClassWithJsonElementExtensionDataWithAttributedConverter : IClassWithOverflow> + public class ClassWithJsonElementExtensionDataWithAttributedConverter : IClassWithOverflow { [JsonExtensionData] [JsonConverter(typeof(JsonElementOverflowConverter))] public Dictionary Overflow { get; set; } + + public IDictionary GetOverflow() => Overflow; } - public class ClassWithCustomElementExtensionDataWithAttributedConverter : IClassWithOverflow> + public class ClassWithCustomElementExtensionDataWithAttributedConverter : IClassWithOverflow { [JsonExtensionData] [JsonConverter(typeof(CustomObjectDictionaryOverflowConverter))] public CustomOverflowDictionary Overflow { get; set; } + + public IDictionary GetOverflow() => Overflow; } - public class ClassWithCustomJsonElementExtensionDataWithAttributedConverter : IClassWithOverflow> + public class ClassWithCustomJsonElementExtensionDataWithAttributedConverter : IClassWithOverflow { [JsonExtensionData] [JsonConverter(typeof(CustomJsonElementDictionaryOverflowConverter))] public CustomOverflowDictionary Overflow { get; set; } + + public IDictionary GetOverflow() => Overflow; } [Theory] - [InlineData(typeof(ClassWithExtensionDataWithAttributedConverter), typeof(Dictionary))] - [InlineData(typeof(ClassWithJsonElementExtensionDataWithAttributedConverter), typeof(Dictionary))] - [InlineData(typeof(ClassWithCustomElementExtensionDataWithAttributedConverter), typeof(CustomOverflowDictionary))] - [InlineData(typeof(ClassWithCustomJsonElementExtensionDataWithAttributedConverter), typeof(CustomOverflowDictionary))] - public void ExtensionProperty_SupportsWritingToCustomSerializerWithExplicitConverter(Type attributedType, Type dictionaryType) + [MemberData(nameof(GetClassesWithCustomExtensionDataOverflowConverter))] + public async Task ExtensionProperty_SupportsWritingToCustomSerializerWithExplicitConverter(ClassWithOverflow obj) where ClassWithOverflow : IClassWithOverflow { - typeof(ExtensionDataTests) - .GetMethod(nameof(ExtensionProperty_SupportsWritingToCustomSerializerWithExplicitConverterInternal), BindingFlags.Static | BindingFlags.NonPublic) - .MakeGenericMethod(attributedType, dictionaryType) - .Invoke(null, null); + string json = await Serializer.SerializeWrapper(obj); + Assert.Equal(@"{""MyCustomOverflowWrite"":""OverflowValueWrite""}", json); } - private static void ExtensionProperty_SupportsWritingToCustomSerializerWithExplicitConverterInternal() - where TRoot : IClassWithOverflow, new() - where TDictionary : new() + [Theory] +#if BUILDING_SOURCE_GENERATOR_TESTS + [ActiveIssue("https://github.com/dotnet/runtime/issues/87005")] +#endif + [MemberData(nameof(GetCustomOverflowConverters))] + public async Task ExtensionProperty_IgnoresCustomSerializerWithOptions(JsonConverter dictionaryConverter) where TDictionary : IDictionary { - var root = new TRoot() - { - Overflow = new TDictionary() - }; + var options = Serializer.CreateOptions(makeReadOnly: false); + options.Converters.Add(dictionaryConverter); - string json = JsonSerializer.Serialize(root); - Assert.Equal(@"{""MyCustomOverflowWrite"":""OverflowValueWrite""}", json); + ClassWithExtensionData obj = await Serializer.DeserializeWrapper>(@"{""TestKey"":""TestValue""}", options); + Assert.Equal("TestValue", ((JsonElement)obj.Overflow["TestKey"]).GetString()); } - [Theory] - [InlineData(typeof(Dictionary), typeof(DictionaryOverflowConverter), typeof(object))] - [InlineData(typeof(Dictionary), typeof(JsonElementOverflowConverter), typeof(JsonElement))] - [InlineData(typeof(CustomOverflowDictionary), typeof(CustomObjectDictionaryOverflowConverter), typeof(object))] - [InlineData(typeof(CustomOverflowDictionary), typeof(CustomJsonElementDictionaryOverflowConverter), typeof(JsonElement))] - public void ExtensionProperty_IgnoresCustomSerializerWithOptions(Type overflowType, Type converterType, Type elementType) + public static IEnumerable GetCustomOverflowConverters() { - typeof(ExtensionDataTests) - .GetMethod(nameof(ExtensionProperty_IgnoresCustomSerializerWithOptionsInternal), BindingFlags.Static | BindingFlags.NonPublic) - .MakeGenericMethod(overflowType, elementType, converterType) - .Invoke(null, null); + yield return WrapArgs(new DictionaryOverflowConverter()); + yield return WrapArgs(new JsonElementOverflowConverter()); + yield return WrapArgs(new CustomObjectDictionaryOverflowConverter()); + yield return WrapArgs(new CustomJsonElementDictionaryOverflowConverter()); + + static object[] WrapArgs(JsonConverter converter) => new object[] { converter }; } [Fact] @@ -541,30 +530,22 @@ public async Task ExtensionProperty_IgnoresCustomSerializerWithOptions_JsonObjec Assert.Contains("JsonObject", ex.ToString()); } - private static void ExtensionProperty_IgnoresCustomSerializerWithOptionsInternal() - where TConverter : JsonConverter, new() - where TDictionary : IDictionary + [Theory] + [MemberData(nameof(GetClassesWithCustomExtensionDataOverflowConverter))] + public async Task ExtensionProperty_IgnoresCustomSerializerWithExplicitConverter(ClassWithOverflow obj) + where ClassWithOverflow : IClassWithOverflow { - var options = new JsonSerializerOptions(); - options.Converters.Add(new TConverter()); - - ClassWithExtensionData obj - = JsonSerializer.Deserialize>(@"{""TestKey"":""TestValue""}", options); - - Assert.Equal("TestValue", ((JsonElement)(object)obj.Overflow["TestKey"]).GetString()); + obj = await Serializer.DeserializeWrapper(@"{""TestKey"":""TestValue""}"); + Assert.Equal("TestValue", ((JsonElement)obj.GetOverflow()["TestKey"]).GetString()); } - [Theory] - [InlineData(typeof(ClassWithExtensionDataWithAttributedConverter), typeof(Dictionary), typeof(object))] - [InlineData(typeof(ClassWithJsonElementExtensionDataWithAttributedConverter), typeof(Dictionary), typeof(JsonElement))] - [InlineData(typeof(ClassWithCustomElementExtensionDataWithAttributedConverter), typeof(CustomOverflowDictionary), typeof(object))] - [InlineData(typeof(ClassWithCustomJsonElementExtensionDataWithAttributedConverter), typeof(CustomOverflowDictionary), typeof(JsonElement))] - public void ExtensionProperty_IgnoresCustomSerializerWithExplicitConverter(Type attributedType, Type dictionaryType, Type elementType) + public static IEnumerable GetClassesWithCustomExtensionDataOverflowConverter() { - typeof(ExtensionDataTests) - .GetMethod(nameof(ExtensionProperty_IgnoresCustomSerializerWithExplicitConverterInternal), BindingFlags.Static | BindingFlags.NonPublic) - .MakeGenericMethod(attributedType, dictionaryType, elementType) - .Invoke(null, null); + yield return WrapArgs(new ClassWithExtensionDataWithAttributedConverter { Overflow = new() }); + yield return WrapArgs(new ClassWithJsonElementExtensionDataWithAttributedConverter { Overflow = new() }); + yield return WrapArgs(new ClassWithCustomElementExtensionDataWithAttributedConverter { Overflow = new() }); + yield return WrapArgs(new ClassWithCustomJsonElementExtensionDataWithAttributedConverter { Overflow = new() }); + static object[] WrapArgs(IClassWithOverflow classWithOverflow) => new object[] { classWithOverflow }; } [Fact] @@ -576,16 +557,6 @@ ClassWithExtensionData obj Assert.Equal("TestValue", obj.Overflow["TestKey"].GetValue()); } - private static void ExtensionProperty_IgnoresCustomSerializerWithExplicitConverterInternal() - where TRoot : IClassWithOverflow, new() - where TDictionary : IDictionary - { - ClassWithExtensionData obj - = JsonSerializer.Deserialize>(@"{""TestKey"":""TestValue""}"); - - Assert.Equal("TestValue", ((JsonElement)(object)obj.Overflow["TestKey"]).GetString()); - } - [Fact] public async Task ExtensionPropertyObjectValue_Empty() { diff --git a/src/libraries/System.Text.Json/tests/Common/JsonCreationHandlingTests.Dictionary.cs b/src/libraries/System.Text.Json/tests/Common/JsonCreationHandlingTests.Dictionary.cs index 9a4b97befd6a16..45a649833f0020 100644 --- a/src/libraries/System.Text.Json/tests/Common/JsonCreationHandlingTests.Dictionary.cs +++ b/src/libraries/System.Text.Json/tests/Common/JsonCreationHandlingTests.Dictionary.cs @@ -4,6 +4,7 @@ using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using Xunit; @@ -580,7 +581,16 @@ internal struct ClassWithReadOnlyPropertyIDictionary_BackedBy_DictionaryOfString public ClassWithReadOnlyPropertyIDictionary_BackedBy_DictionaryOfStringToJsonElement() {} [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)] - public IDictionary Property { get; } = JsonSerializer.Deserialize>("""{"a":1,"b":2,"c":3}"""); + public IDictionary Property { get; } = ParseJsonObject("""{"a":1,"b":2,"c":3}""").ToDictionary(kv => kv.Key, kv => kv.Value); + } + + private static IEnumerable> ParseJsonObject(string json) + { + JsonDocument doc = JsonDocument.Parse(json); + foreach (var entry in doc.RootElement.EnumerateObject()) + { + yield return new KeyValuePair(entry.Name, entry.Value); + } } [Fact] @@ -625,7 +635,7 @@ internal struct ClassWithReadOnlyPropertyIDictionary_BackedBy_DictionaryOfString { public ClassWithReadOnlyPropertyIDictionary_BackedBy_DictionaryOfStringToJsonElementWithoutPopulateAttribute() {} - public IDictionary Property { get; } = JsonSerializer.Deserialize>("""{"a":1,"b":2,"c":3}"""); + public IDictionary Property { get; } = ParseJsonObject("""{"a":1,"b":2,"c":3}""").ToDictionary(kv => kv.Key, kv => kv.Value); } [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)] @@ -633,7 +643,7 @@ internal struct ClassWithReadOnlyPropertyIDictionary_BackedBy_DictionaryOfString { public ClassWithReadOnlyPropertyIDictionary_BackedBy_DictionaryOfStringToJsonElementWithAttributeOnType() {} - public IDictionary Property { get; } = JsonSerializer.Deserialize>("""{"a":1,"b":2,"c":3}"""); + public IDictionary Property { get; } = ParseJsonObject("""{"a":1,"b":2,"c":3}""").ToDictionary(kv => kv.Key, kv => kv.Value); } [Fact] @@ -670,7 +680,7 @@ public async Task CreationHandlingSetWithAttribute_CanPopulate_IDictionary_Backe internal class ClassWithReadOnlyPropertyIDictionary_BackedBy_StructDictionaryOfStringToJsonElement { [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)] - public IDictionary Property { get; } = JsonSerializer.Deserialize>("""{"a":1,"b":2,"c":3}"""); + public IDictionary Property { get; } = new StructDictionary(ParseJsonObject("""{"a":1,"b":2,"c":3}""")); } [Fact] @@ -716,13 +726,13 @@ public async Task CreationHandlingSetWithOptions_CanPopulate_IDictionary_BackedB internal class ClassWithReadOnlyPropertyIDictionary_BackedBy_StructDictionaryOfStringToJsonElementWithoutPopulateAttribute { - public IDictionary Property { get; } = JsonSerializer.Deserialize>("""{"a":1,"b":2,"c":3}"""); + public IDictionary Property { get; } = new StructDictionary(ParseJsonObject("""{"a":1,"b":2,"c":3}""")); } [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)] internal class ClassWithReadOnlyPropertyIDictionary_BackedBy_StructDictionaryOfStringToJsonElementWithAttributeOnType { - public IDictionary Property { get; } = JsonSerializer.Deserialize>("""{"a":1,"b":2,"c":3}"""); + public IDictionary Property { get; } = new StructDictionary(ParseJsonObject("""{"a":1,"b":2,"c":3}""")); } [Fact] diff --git a/src/libraries/System.Text.Json/tests/Common/JsonCreationHandlingTests.Enumerable.cs b/src/libraries/System.Text.Json/tests/Common/JsonCreationHandlingTests.Enumerable.cs index 23ae7662d72531..afe884ad5e7dbc 100644 --- a/src/libraries/System.Text.Json/tests/Common/JsonCreationHandlingTests.Enumerable.cs +++ b/src/libraries/System.Text.Json/tests/Common/JsonCreationHandlingTests.Enumerable.cs @@ -582,7 +582,16 @@ internal struct ClassWithReadOnlyPropertyIList_BackedBy_ListOfJsonElement public ClassWithReadOnlyPropertyIList_BackedBy_ListOfJsonElement() {} [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)] - public IList Property { get; } = JsonSerializer.Deserialize>("[1,2,3]"); + public IList Property { get; } = new List(ParseJsonArray("[1,2,3]")); + } + + private static IEnumerable ParseJsonArray(string json) + { + JsonDocument doc = JsonDocument.Parse(json); + foreach (JsonElement element in doc.RootElement.EnumerateArray()) + { + yield return element; + } } [Fact] @@ -627,7 +636,7 @@ internal struct ClassWithReadOnlyPropertyIList_BackedBy_ListOfJsonElementWithout { public ClassWithReadOnlyPropertyIList_BackedBy_ListOfJsonElementWithoutPopulateAttribute() {} - public IList Property { get; } = JsonSerializer.Deserialize>("[1,2,3]"); + public IList Property { get; } = new List(ParseJsonArray("[1,2,3]")); } [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)] @@ -635,7 +644,7 @@ internal struct ClassWithReadOnlyPropertyIList_BackedBy_ListOfJsonElementWithAtt { public ClassWithReadOnlyPropertyIList_BackedBy_ListOfJsonElementWithAttributeOnType() {} - public IList Property { get; } = JsonSerializer.Deserialize>("[1,2,3]"); + public IList Property { get; } = new List(ParseJsonArray("[1,2,3]")); } [Fact] @@ -672,7 +681,7 @@ public async Task CreationHandlingSetWithAttribute_CanPopulate_IList_BackedBy_St internal class ClassWithReadOnlyPropertyIList_BackedBy_StructListOfJsonElement { [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)] - public IList Property { get; } = JsonSerializer.Deserialize>("[1,2,3]"); + public IList Property { get; } = new StructList(ParseJsonArray("[1,2,3]")); } [Fact] @@ -718,13 +727,13 @@ public async Task CreationHandlingSetWithOptions_CanPopulate_IList_BackedBy_Stru internal class ClassWithReadOnlyPropertyIList_BackedBy_StructListOfJsonElementWithoutPopulateAttribute { - public IList Property { get; } = JsonSerializer.Deserialize>("[1,2,3]"); + public IList Property { get; } = new StructList(ParseJsonArray("[1,2,3]")); } [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)] internal class ClassWithReadOnlyPropertyIList_BackedBy_StructListOfJsonElementWithAttributeOnType { - public IList Property { get; } = JsonSerializer.Deserialize>("[1,2,3]"); + public IList Property { get; } = new StructList(ParseJsonArray("[1,2,3]")); } [Fact] @@ -1229,7 +1238,7 @@ internal struct ClassWithReadOnlyPropertyQueue public ClassWithReadOnlyPropertyQueue() {} [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)] - public Queue Property { get; } = JsonSerializer.Deserialize("[1,2,3]"); + public Queue Property { get; } = new Queue(ParseJsonArray("[1,2,3]").ToArray()); } [Fact] @@ -1274,7 +1283,7 @@ internal struct ClassWithReadOnlyPropertyQueueWithoutPopulateAttribute { public ClassWithReadOnlyPropertyQueueWithoutPopulateAttribute() {} - public Queue Property { get; } = JsonSerializer.Deserialize("[1,2,3]"); + public Queue Property { get; } = new Queue(ParseJsonArray("[1,2,3]").ToArray()); } [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)] @@ -1282,7 +1291,7 @@ internal struct ClassWithReadOnlyPropertyQueueWithAttributeOnType { public ClassWithReadOnlyPropertyQueueWithAttributeOnType() {} - public Queue Property { get; } = JsonSerializer.Deserialize("[1,2,3]"); + public Queue Property { get; } = new Queue(ParseJsonArray("[1,2,3]").ToArray()); } [Fact] @@ -1677,7 +1686,7 @@ internal struct ClassWithReadOnlyPropertyStack public ClassWithReadOnlyPropertyStack() {} [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)] - public Stack Property { get; } = JsonSerializer.Deserialize("[1,2,3]"); + public Stack Property { get; } = new Stack(ParseJsonArray("[1,2,3]").ToArray()); } [Fact] @@ -1722,7 +1731,7 @@ internal struct ClassWithReadOnlyPropertyStackWithoutPopulateAttribute { public ClassWithReadOnlyPropertyStackWithoutPopulateAttribute() {} - public Stack Property { get; } = JsonSerializer.Deserialize("[1,2,3]"); + public Stack Property { get; } = new Stack(ParseJsonArray("[1,2,3]").ToArray()); } [JsonObjectCreationHandling(JsonObjectCreationHandling.Populate)] @@ -1730,7 +1739,7 @@ internal struct ClassWithReadOnlyPropertyStackWithAttributeOnType { public ClassWithReadOnlyPropertyStackWithAttributeOnType() {} - public Stack Property { get; } = JsonSerializer.Deserialize("[1,2,3]"); + public Stack Property { get; } = new Stack(ParseJsonArray("[1,2,3]").ToArray()); } [Fact] diff --git a/src/libraries/System.Text.Json/tests/Common/JsonCreationHandlingTests.Generic.cs b/src/libraries/System.Text.Json/tests/Common/JsonCreationHandlingTests.Generic.cs index ca5e6c89b631eb..1937f5fe73a19b 100644 --- a/src/libraries/System.Text.Json/tests/Common/JsonCreationHandlingTests.Generic.cs +++ b/src/libraries/System.Text.Json/tests/Common/JsonCreationHandlingTests.Generic.cs @@ -8,7 +8,6 @@ using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; using System.Linq; -using System.Reflection; using System.Text.Json.Serialization.Metadata; using System.Threading.Tasks; using Xunit; @@ -42,8 +41,15 @@ object IList.this[int index] set => _list[index] = (T)value; } + [JsonConstructor] public StructList() { } + public StructList(IEnumerable values) + { + _list.AddRange(values); + _count = _list.Count; + } + public void Add(T item) { _count++; @@ -261,8 +267,15 @@ internal struct StructDictionary : IDictionary, IDic // we track count separately to make sure tests are not passing by accident because we use reference to list inside of struct private int _count; + [JsonConstructor] public StructDictionary() { } + public StructDictionary(IEnumerable> entries) + { + _dict = entries.ToDictionary(kv => kv.Key, kv => kv.Value); + _count = _dict.Count; + } + public TValue this[TKey key] { get => _dict[key]; @@ -415,123 +428,99 @@ public async Task CreationHandlingSetWithAttribute_PopulateSetWithModifierWithIn } [Theory] - [InlineData(typeof(List))] - [InlineData(typeof(IList))] - [InlineData(typeof(IList))] - [InlineData(typeof(Queue))] - [InlineData(typeof(Queue))] - [InlineData(typeof(ConcurrentQueue))] - [InlineData(typeof(Stack))] - [InlineData(typeof(Stack))] - [InlineData(typeof(ConcurrentStack))] - [InlineData(typeof(ICollection))] - [InlineData(typeof(ISet))] - [InlineData(typeof(Dictionary))] - [InlineData(typeof(IDictionary))] - [InlineData(typeof(IDictionary))] - [InlineData(typeof(ConcurrentDictionary))] - [InlineData(typeof(SortedDictionary))] - public Task CreationHandlingSetWithAttribute_PopulatedPropertyDeserializeNull(Type type) - { - return (Task)typeof(JsonCreationHandlingTests) - .GetMethod(nameof(CreationHandling_PopulatedPropertyDeserializeNullGeneric), BindingFlags.NonPublic | BindingFlags.Instance) - .MakeGenericMethod(type).Invoke(this, null); - } - - private async Task CreationHandling_PopulatedPropertyDeserializeNullGeneric() - { - JsonSerializerOptions options = Serializer.CreateOptions(); - string json = """{"Property":null}"""; - var obj = await Serializer.DeserializeWrapper>(json, options); - Assert.Null(obj.Property); - } + [MemberData(nameof(GetTestedCollectionTypes))] + public Task CreationHandlingSetWithAttribute_PopulatedPropertyDeserializeNull(TypeWitness typeWitness) + => typeWitness.Accept(CreationHandling_PopulatedPropertyDeserializeNull_TestBody.Instance, Serializer); - [Theory] - [InlineData(typeof(List))] - [InlineData(typeof(IList))] - [InlineData(typeof(IList))] - [InlineData(typeof(Queue))] - [InlineData(typeof(Queue))] - [InlineData(typeof(ConcurrentQueue))] - [InlineData(typeof(Stack))] - [InlineData(typeof(Stack))] - [InlineData(typeof(ConcurrentStack))] - [InlineData(typeof(ICollection))] - [InlineData(typeof(ISet))] - [InlineData(typeof(Dictionary))] - [InlineData(typeof(IDictionary))] - [InlineData(typeof(IDictionary))] - [InlineData(typeof(ConcurrentDictionary))] - [InlineData(typeof(SortedDictionary))] - public Task CreationHandlingSetWithAttribute_PopulatedPropertyDeserializeNullOnReadOnlyProperty(Type type) - { - return (Task)typeof(JsonCreationHandlingTests) - .GetMethod(nameof(CreationHandling_PopulatedPropertyDeserializeNullOnReadOnlyPropertyGeneric), BindingFlags.NonPublic | BindingFlags.Instance) - .MakeGenericMethod(type).Invoke(this, null); - } - - private async Task CreationHandling_PopulatedPropertyDeserializeNullOnReadOnlyPropertyGeneric() - { - JsonSerializerOptions options = Serializer.CreateOptions(); - string json = """{"Property":null}"""; - await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper>(json, options)); + private sealed class CreationHandling_PopulatedPropertyDeserializeNull_TestBody : ITypeVisitor + { + public readonly static CreationHandling_PopulatedPropertyDeserializeNull_TestBody Instance = new(); + public async Task Visit(JsonSerializerWrapper serializer) + { + string json = """{"Property":null}"""; + var obj = await serializer.DeserializeWrapper>(json); + Assert.Null(obj.Property); + } } [Theory] - [InlineData(typeof(List), true)] - [InlineData(typeof(IList), true)] - [InlineData(typeof(IList), true)] - [InlineData(typeof(Queue), true)] - [InlineData(typeof(Queue), true)] - [InlineData(typeof(ConcurrentQueue), true)] - [InlineData(typeof(Stack), true)] - [InlineData(typeof(Stack), true)] - [InlineData(typeof(ConcurrentStack), true)] - [InlineData(typeof(ICollection), true)] - [InlineData(typeof(ISet), true)] - [InlineData(typeof(Dictionary), false)] - [InlineData(typeof(IDictionary), false)] - [InlineData(typeof(IDictionary), false)] - [InlineData(typeof(ConcurrentDictionary), false)] - [InlineData(typeof(SortedDictionary), false)] - [InlineData(typeof(StructList?), true)] - [InlineData(typeof(StructCollection?), true)] - [InlineData(typeof(StructSet?), true)] - [InlineData(typeof(StructDictionary?), false)] - public Task CreationHandlingSetWithAttribute_PopulatedPropertyDeserializeInitiallyNull(Type type, bool isArray) - { - return (Task)typeof(JsonCreationHandlingTests) - .GetMethod(nameof(CreationHandling_PopulatedPropertyDeserializeInitiallyNullGeneric), BindingFlags.NonPublic | BindingFlags.Instance) - .MakeGenericMethod(type).Invoke(this, new object[] { isArray }); - } - - private async Task CreationHandling_PopulatedPropertyDeserializeInitiallyNullGeneric(bool isArray) - { - JsonSerializerOptions options = Serializer.CreateOptions(); - string json = isArray ? """{"Property":[1,2,3]}""" : """{"Property":{"a":1,"b":2,"c":3}}"""; - - if (typeof(T).IsValueType) + [MemberData(nameof(GetTestedCollectionTypes))] + public Task CreationHandlingSetWithAttribute_PopulatedPropertyDeserializeNullOnReadOnlyProperty(TypeWitness typeWitness) + => typeWitness.Accept(CreationHandling_PopulatedPropertyDeserializeNullOnReadOnlyPropertyGeneric_TestBody.Instance, Serializer); + + private sealed class CreationHandling_PopulatedPropertyDeserializeNullOnReadOnlyPropertyGeneric_TestBody : ITypeVisitor + { + public readonly static CreationHandling_PopulatedPropertyDeserializeNullOnReadOnlyPropertyGeneric_TestBody Instance = new(); + public async Task Visit(JsonSerializerWrapper serializer) { - await Assert.ThrowsAsync(async () => await Serializer.DeserializeWrapper>("{}", options)); + string json = """{"Property":null}"""; + await Assert.ThrowsAsync(async () => await serializer.DeserializeWrapper>(json)); } - else - { - var obj = await Serializer.DeserializeWrapper>("{}", options); - Assert.Null(obj.Property); + } - obj = await Serializer.DeserializeWrapper>(json, options); - Assert.Null(obj.Property); - } + [Theory] + [MemberData(nameof(GetTestedCollectionTypes))] + public Task CreationHandlingSetWithAttribute_PopulatedPropertyDeserializeInitiallyNull(TypeWitness typeWitness) + => typeWitness.Accept(CreationHandlingSetWithAttribute_PopulatedPropertyDeserializeInitiallyNull_TestBody.Instance, Serializer); + private sealed class CreationHandlingSetWithAttribute_PopulatedPropertyDeserializeInitiallyNull_TestBody : ITypeVisitor + { + public readonly static CreationHandlingSetWithAttribute_PopulatedPropertyDeserializeInitiallyNull_TestBody Instance = new(); + public async Task Visit(JsonSerializerWrapper serializer) { - var obj = await Serializer.DeserializeWrapper>("{}", options); - Assert.Null(obj.Property); + JsonTypeInfoKind kind = serializer.DefaultOptions.GetTypeInfo(typeof(T)).Kind; + Assert.True(kind is JsonTypeInfoKind.Enumerable or JsonTypeInfoKind.Dictionary); + string json = kind is JsonTypeInfoKind.Enumerable ? """{"Property":[1,2,3]}""" : """{"Property":{"a":1,"b":2,"c":3}}"""; + + if (typeof(T).IsValueType) + { + await Assert.ThrowsAsync(async () => await serializer.DeserializeWrapper>("{}")); + } + else + { + var obj = await serializer.DeserializeWrapper>("{}"); + Assert.Null(obj.Property); + + obj = await serializer.DeserializeWrapper>(json); + Assert.Null(obj.Property); + } + + { + var obj = await serializer.DeserializeWrapper>("{}"); + Assert.Null(obj.Property); - obj = await Serializer.DeserializeWrapper>(json, options); - Assert.NotNull(obj.Property); + obj = await serializer.DeserializeWrapper>(json); + Assert.NotNull(obj.Property); + } } } + public static IEnumerable GetTestedCollectionTypes() + { + yield return Wrap(new TypeWitness>()); + yield return Wrap(new TypeWitness>()); + yield return Wrap(new TypeWitness()); + yield return Wrap(new TypeWitness>()); + yield return Wrap(new TypeWitness()); + yield return Wrap(new TypeWitness>()); + yield return Wrap(new TypeWitness>()); + yield return Wrap(new TypeWitness()); + yield return Wrap(new TypeWitness>()); + yield return Wrap(new TypeWitness>()); + yield return Wrap(new TypeWitness>()); + yield return Wrap(new TypeWitness>()); + yield return Wrap(new TypeWitness>()); + yield return Wrap(new TypeWitness()); + yield return Wrap(new TypeWitness>()); + yield return Wrap(new TypeWitness>()); + yield return Wrap(new TypeWitness?>()); + yield return Wrap(new TypeWitness?>()); + yield return Wrap(new TypeWitness?>()); + yield return Wrap(new TypeWitness?>()); + + static object[] Wrap(TypeWitness witness) => new object[] { witness }; + } + private static void CheckGenericDictionaryContent(IDictionary dict, int expectedNumberOfElements = 6) { Assert.Equal(expectedNumberOfElements, dict.Count); diff --git a/src/libraries/System.Text.Json/tests/Common/JsonSerializerWrapper.cs b/src/libraries/System.Text.Json/tests/Common/JsonSerializerWrapper.cs index 159bd389dec0b9..259e363555f357 100644 --- a/src/libraries/System.Text.Json/tests/Common/JsonSerializerWrapper.cs +++ b/src/libraries/System.Text.Json/tests/Common/JsonSerializerWrapper.cs @@ -65,18 +65,22 @@ public JsonSerializerOptions GetDefaultOptionsWithMetadataModifier(Action configure = null, - bool includeFields = false, - List customConverters = null, - Action modifier = null) + bool? includeFields = false, + List? customConverters = null, + Action? modifier = null, + bool makeReadOnly = true) { - IJsonTypeInfoResolver resolver = DefaultOptions.TypeInfoResolver; - resolver = modifier != null ? resolver.WithModifier(modifier) : resolver; + var options = new JsonSerializerOptions(DefaultOptions); - JsonSerializerOptions options = new() + if (includeFields != null) { - TypeInfoResolver = resolver, - IncludeFields = includeFields, - }; + options.IncludeFields = includeFields.Value; + } + + if (modifier != null && options.TypeInfoResolver != null) + { + options.TypeInfoResolver = DefaultOptions.TypeInfoResolver.WithModifier(modifier); + } if (customConverters != null) { @@ -88,7 +92,10 @@ public JsonSerializerOptions CreateOptions( configure?.Invoke(options); - options.MakeReadOnly(); + if (makeReadOnly) + { + options.MakeReadOnly(); + } return options; } diff --git a/src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs b/src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs index 08addddca85175..03961e98ba6a69 100644 --- a/src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs +++ b/src/libraries/System.Text.Json/tests/Common/JsonTestHelper.cs @@ -188,4 +188,28 @@ public static async Task> ToListAsync(this IAsyncEnumerable source public static string StripWhitespace(this string value) => s_stripWhitespace.Replace(value, string.Empty); } + + /// + /// Generic visitor pattern used for safely invoking generic methods in AOT. + /// + public abstract class TypeWitness + { + public abstract TResult Accept(ITypeVisitor visitor, TState state); + } + + /// + /// Generic visitor pattern used for safely invoking generic methods in AOT. + /// + public sealed class TypeWitness : TypeWitness + { + public override TResult Accept(ITypeVisitor visitor, TState state) => visitor.Visit(state); + } + + /// + /// Generic visitor pattern used for safely invoking generic methods in AOT. + /// + public interface ITypeVisitor + { + public TResult Visit(TState state); + } } diff --git a/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs b/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs index e0e4e3ab2dd067..4c0b7960ae5bd2 100644 --- a/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs +++ b/src/libraries/System.Text.Json/tests/Common/PropertyVisibilityTests.cs @@ -1,9 +1,11 @@ // 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; using System.Collections.Concurrent; +using System.Collections.Generic; using System.Numerics; +using System.Text.Json.Serialization.Metadata; using System.Threading.Tasks; using Xunit; @@ -241,6 +243,22 @@ public async Task Ignore_BasePublicPropertyIgnored_ConflictWithDerivedPrivate() Assert.Equal("NewDefaultValue", ((ClassWithIgnoredPublicPropertyAndNewSlotPrivate)obj).MyString); } + [Fact] + public async void Ignore_BasePublicPropertyIgnored_ConflictWithDerivedPublicPropertyIgnored() + { + var obj = new ClassWithIgnoredPublicPropertyAndNewSlotPublicAndIgnoredToo(); + + string json = await Serializer.SerializeWrapper(obj); + + Assert.Equal(@"{}", json); + + json = @"{""MyString"":""NewValue""}"; + obj = await Serializer.DeserializeWrapper(json); + + Assert.Equal("DefaultValue", ((ClassWithIgnoredPublicProperty)obj).MyString); + Assert.Equal("NewDefaultValue", obj.MyString); + } + [Fact] public async Task Ignore_VerifyNoReferenceToGetterAndSetter() { @@ -812,6 +830,12 @@ public class ClassWithIgnoredPublicPropertyAndNewSlotPrivate : ClassWithIgnoredP internal new string MyString { get; set; } = "NewDefaultValue"; } + public class ClassWithIgnoredPublicPropertyAndNewSlotPublicAndIgnoredToo : ClassWithIgnoredPublicProperty + { + [JsonIgnore] + public new string MyString { get; set; } = "NewDefaultValue"; + } + public class ClassWithIgnoredPropertyNamingConflictPrivate { [JsonIgnore] @@ -1067,6 +1091,138 @@ ClassWithPublicGetterAndPrivateSetter obj Assert.Null(obj.Class); } + [Fact] + public async Task ProtectedMembers() + { + var options = Serializer.CreateOptions(includeFields: true); + JsonTypeInfo typeInfo = options.GetTypeInfo(typeof(ClassWithProtectedMembers)); + Assert.Empty(typeInfo.Properties); + + var value = new ClassWithProtectedMembers(); + value.SetValues(field: 10, property: 20); + + string json = await Serializer.SerializeWrapper(value, options); + Assert.Equal("{}", json); + + value = await Serializer.DeserializeWrapper("""{"_field":10,"Property":20}"""); + value.GetValues(out int field, out int property); + Assert.Equal(0, field); + Assert.Equal(0, property); + } + + [Fact] + public async Task ProtectedGetter() + { + var value = new ClassWithProtectedGetter { Property = 42 }; + + string json = await Serializer.SerializeWrapper(value); + Assert.Equal("{}", json); + + value = await Serializer.DeserializeWrapper("""{"Property":42}"""); + Assert.Equal(42, value.GetValue()); + } + + [Fact] + public async Task ProtectedSetter() + { + var value = new ClassWithProtectedSetter(); + value.SetValue(42); + + string json = await Serializer.SerializeWrapper(value); + Assert.Equal("""{"Property":42}""", json); + + value = await Serializer.DeserializeWrapper(json); + Assert.Equal(0, value.Property); + } + + [Fact] + public async Task PrivateProtectedMembers() + { + var options = Serializer.CreateOptions(includeFields: true); + JsonTypeInfo typeInfo = options.GetTypeInfo(typeof(ClassWithPrivateProtectedMembers)); + Assert.Empty(typeInfo.Properties); + + var value = new ClassWithPrivateProtectedMembers(); + value.SetValues(field: 10, property: 20); + + string json = await Serializer.SerializeWrapper(value, options); + Assert.Equal("{}", json); + + value = await Serializer.DeserializeWrapper("""{"_field":10,"Property":20}"""); + value.GetValues(out int field, out int property); + Assert.Equal(0, field); + Assert.Equal(0, property); + } + + [Fact] + public async Task PrivateProtectedGetter() + { + var value = new ClassWithPrivateProtectedGetter { Property = 42 }; + + string json = await Serializer.SerializeWrapper(value); + Assert.Equal("{}", json); + + value = await Serializer.DeserializeWrapper("""{"Property":42}"""); + Assert.Equal(42, value.GetValue()); + } + + [Fact] + public async Task PrivateProtectedSetter() + { + var value = new ClassWithPrivateProtectedSetter(); + value.SetValue(42); + + string json = await Serializer.SerializeWrapper(value); + Assert.Equal("""{"Property":42}""", json); + + value = await Serializer.DeserializeWrapper(json); + Assert.Equal(0, value.Property); + } + + [Fact] + public async Task InternalProtectedMembers() + { + var options = Serializer.CreateOptions(includeFields: true); + JsonTypeInfo typeInfo = options.GetTypeInfo(typeof(ClassWithInternalProtectedMembers)); + Assert.Empty(typeInfo.Properties); + + var value = new ClassWithInternalProtectedMembers(); + value.SetValues(field: 10, property: 20); + + string json = await Serializer.SerializeWrapper(value, options); + Assert.Equal("{}", json); + + value = await Serializer.DeserializeWrapper("""{"_field":10,"Property":20}"""); + value.GetValues(out int field, out int property); + Assert.Equal(0, field); + Assert.Equal(0, property); + } + + [Fact] + public async Task InternalProtectedGetter() + { + var value = new ClassWithInternalProtectedGetter { Property = 42 }; + + string json = await Serializer.SerializeWrapper(value); + Assert.Equal("{}", json); + + value = await Serializer.DeserializeWrapper("""{"Property":42}"""); + Assert.Equal(42, value.GetValue()); + } + + [Fact] + public async Task InternalProtectedSetter() + { + var value = new ClassWithInternalProtectedSetter(); + value.SetValue(42); + + string json = await Serializer.SerializeWrapper(value); + Assert.Equal("""{"Property":42}""", json); + + value = await Serializer.DeserializeWrapper(json); + Assert.Equal(0, value.Property); + } + [Fact] public async Task MissingObjectProperty() { @@ -1333,6 +1489,69 @@ public void SetMyString(string value) } } + public class ClassWithProtectedMembers + { + protected int _field; + protected int Property { get; set; } + + public void SetValues(int field, int property) => (_field, Property) = (field, property); + public void GetValues(out int field, out int property) => (field, property) = (_field, Property); + } + + public class ClassWithProtectedGetter + { + public int Property { protected get; set; } + public int GetValue() => Property; + } + + public class ClassWithProtectedSetter + { + public int Property { get; protected set; } + public void SetValue(int value) => Property = value; + } + + public class ClassWithPrivateProtectedMembers + { + private protected int _field; + private protected int Property { get; set; } + + public void SetValues(int field, int property) => (_field, Property) = (field, property); + public void GetValues(out int field, out int property) => (field, property) = (_field, Property); + } + + public class ClassWithPrivateProtectedGetter + { + public int Property { private protected get; set; } + public int GetValue() => Property; + } + + public class ClassWithPrivateProtectedSetter + { + public int Property { get; private protected set; } + public void SetValue(int value) => Property = value; + } + + public class ClassWithInternalProtectedMembers + { + protected internal int _field; + protected internal int Property { get; set; } + + public void SetValues(int field, int property) => (_field, Property) = (field, property); + public void GetValues(out int field, out int property) => (field, property) = (_field, Property); + } + + public class ClassWithInternalProtectedGetter + { + public int Property { internal protected get; set; } + public int GetValue() => Property; + } + + public class ClassWithInternalProtectedSetter + { + public int Property { get; internal protected set; } + public void SetValue(int value) => Property = value; + } + public class ClassWithReadOnlyFields { public ClassWithReadOnlyFields() @@ -3006,5 +3225,84 @@ public class Implementation : IJoinInterface public int DerivedProperty { get; set; } } } + + [Fact] + public async virtual Task TestCollectionWithPrivateElementType() + { + // The reflection-based serializer supports enumerables whose element type is private. + + CollectionWithPrivateElementType collection = CollectionWithPrivateElementType.CreatePopulatedInstance(); + + string json = await Serializer.SerializeWrapper(collection); + Assert.Equal(collection.GetExpectedJson(), json); + + collection = await Serializer.DeserializeWrapper(json); + collection.Validate(); + } + + public class CollectionWithPrivateElementType : ICollection + { + private readonly ICollection _values = new List(); + + public static CollectionWithPrivateElementType CreatePopulatedInstance() + => new CollectionWithPrivateElementType { _values = { PrivateEnum.A, PrivateEnum.B, PrivateEnum.C } }; + + public void Validate() => Assert.Equal(new[] { PrivateEnum.A, PrivateEnum.B, PrivateEnum.C }, this); + public string GetExpectedJson() => "[0,1,2]"; + + int ICollection.Count => _values.Count; + bool ICollection.IsReadOnly => _values.IsReadOnly; + void ICollection.Add(PrivateEnum item) => _values.Add(item); + void ICollection.Clear() => _values.Clear(); + bool ICollection.Contains(PrivateEnum item) => _values.Contains(item); + void ICollection.CopyTo(PrivateEnum[] array, int arrayIndex) => _values.CopyTo(array, arrayIndex); + IEnumerator IEnumerable.GetEnumerator() => _values.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _values.GetEnumerator(); + bool ICollection.Remove(PrivateEnum item) => _values.Remove(item); + } + + [Fact] + public async virtual Task TestDictionaryWithPrivateKeyAndValueType() + { + // The reflection-based serializer supports dictionaries whose key/value types are private + + DictionaryWithPrivateKeyAndValueType collection = DictionaryWithPrivateKeyAndValueType.CreatePopulatedInstance(); + + string json = await Serializer.SerializeWrapper(collection); + Assert.Equal(collection.GetExpectedJson(), json); + + collection = await Serializer.DeserializeWrapper(json); + collection.Validate(); + } + + public class DictionaryWithPrivateKeyAndValueType : IDictionary + { + private readonly IDictionary _values = new Dictionary(); + + public static DictionaryWithPrivateKeyAndValueType CreatePopulatedInstance() + => new DictionaryWithPrivateKeyAndValueType { _values = { [PrivateEnum.A] = PrivateEnum.B, [PrivateEnum.B] = PrivateEnum.C } }; + + public void Validate() => Assert.Equal(new KeyValuePair[] { new(PrivateEnum.A, PrivateEnum.B), new(PrivateEnum.B, PrivateEnum.C) }, this); + public string GetExpectedJson() => """{"A":1,"B":2}"""; + + PrivateEnum IDictionary.this[PrivateEnum key] { get => _values[key]; set => _values[key] = value; } + ICollection IDictionary.Keys => _values.Keys; + ICollection IDictionary.Values => _values.Values; + int ICollection>.Count => _values.Count; + bool ICollection>.IsReadOnly => _values.IsReadOnly; + void IDictionary.Add(PrivateEnum key, PrivateEnum value) => _values.Add(key, value); + void ICollection>.Add(KeyValuePair item) => _values.Add(item); + void ICollection>.Clear() => _values.Clear(); + bool ICollection>.Contains(KeyValuePair item) => _values.Contains(item); + bool IDictionary.ContainsKey(PrivateEnum key) => _values.ContainsKey(key); + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) => _values.CopyTo(array, arrayIndex); + IEnumerator> IEnumerable>.GetEnumerator() => _values.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _values.GetEnumerator(); + bool IDictionary.Remove(PrivateEnum key) => _values.Remove(key); + bool ICollection>.Remove(KeyValuePair item) => _values.Remove(item); + bool IDictionary.TryGetValue(PrivateEnum key, out PrivateEnum value) => _values.TryGetValue(key, out value); + } + + private enum PrivateEnum { A = 0, B = 1, C = 2 } } } diff --git a/src/libraries/System.Text.Json/tests/Common/ReferenceHandlerTests/ReferenceHandlerTests.Serialize.cs b/src/libraries/System.Text.Json/tests/Common/ReferenceHandlerTests/ReferenceHandlerTests.Serialize.cs index caecc062d84adc..6fde273fed85b5 100644 --- a/src/libraries/System.Text.Json/tests/Common/ReferenceHandlerTests/ReferenceHandlerTests.Serialize.cs +++ b/src/libraries/System.Text.Json/tests/Common/ReferenceHandlerTests/ReferenceHandlerTests.Serialize.cs @@ -29,7 +29,7 @@ public class Employee public Dictionary ContactsString { get; set; } = new Dictionary() { { "Bob", "555-5555" } }; } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotNativeAot))] public async Task ExtensionDataDictionaryHandlesPreserveReferences() { Employee bob = new Employee { Name = "Bob" }; diff --git a/src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.Constructor.cs b/src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.Constructor.cs index 8f6df2d166749a..285c5b78934733 100644 --- a/src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.Constructor.cs +++ b/src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.Constructor.cs @@ -659,60 +659,33 @@ public void Verify() Assert.Equal("f2c92fcc-459f-4287-90b6-a7cbd82aeb0e", Id.ToString()); Assert.Equal(24, Age); - string serialized = JsonSerializer.Serialize(this); - Assert.Contains(@"""Point2D"":{", serialized); - Assert.Contains(@"""ReadOnlyPoint2D"":{", serialized); - Assert.Contains(@"""Point2DWithExtDataClass"":{", serialized); - Assert.Contains(@"""ReadOnlyPoint2DWithExtDataClass"":{", serialized); - Assert.Contains(@"""Point3DStruct"":{", serialized); - Assert.Contains(@"""ReadOnlyPoint3DStruct"":{", serialized); - Assert.Contains(@"""Point2DWithExtData"":{", serialized); - Assert.Contains(@"""ReadOnlyPoint2DWithExtData"":{", serialized); - - serialized = JsonSerializer.Serialize(Point2D); - Assert.Contains(@"""X"":1", serialized); - Assert.Contains(@"""Y"":2", serialized); - - serialized = JsonSerializer.Serialize(ReadOnlyPoint2D); - Assert.Contains(@"""X"":1", serialized); - Assert.Contains(@"""Y"":2", serialized); - - serialized = JsonSerializer.Serialize(Point2DWithExtDataClass); - Assert.Contains(@"""X"":1", serialized); - Assert.Contains(@"""Y"":2", serialized); - Assert.Contains(@"""b"":3", serialized); - - serialized = JsonSerializer.Serialize(ReadOnlyPoint2DWithExtDataClass); - Assert.Contains(@"""X"":1", serialized); - Assert.Contains(@"""Y"":2", serialized); - Assert.Contains(@"""b"":3", serialized); - - serialized = JsonSerializer.Serialize(Point3DStruct); - Assert.Contains(@"""X"":1", serialized); - Assert.Contains(@"""Y"":2", serialized); - Assert.Contains(@"""Z"":3", serialized); - - serialized = JsonSerializer.Serialize(ReadOnlyPoint3DStruct); - Assert.Contains(@"""X"":1", serialized); - Assert.Contains(@"""Y"":2", serialized); - Assert.Contains(@"""Z"":3", serialized); - - serialized = JsonSerializer.Serialize(Point2DWithExtData); - Assert.Contains(@"""X"":1", serialized); - Assert.Contains(@"""Y"":2", serialized); - Assert.Contains(@"""b"":3", serialized); - - serialized = JsonSerializer.Serialize(ReadOnlyPoint2DWithExtData); - Assert.Contains(@"""X"":1", serialized); - Assert.Contains(@"""Y"":2", serialized); - Assert.Contains(@"""b"":3", serialized); + Point2D.Verify(); + ReadOnlyPoint2D.Verify(); + + Assert.Equal(1, Point2DWithExtDataClass.X); + Assert.Equal(2, Point2DWithExtDataClass.Y); + Assert.True(Point2DWithExtDataClass.ExtensionData.ContainsKey("b")); + + Assert.Equal(1, Point3DStruct.X); + Assert.Equal(2, Point3DStruct.Y); + Assert.Equal(3, Point3DStruct.Z); + + Assert.Equal(1, ReadOnlyPoint3DStruct.X); + Assert.Equal(2, ReadOnlyPoint3DStruct.Y); + Assert.Equal(3, ReadOnlyPoint3DStruct.Z); + + Assert.Equal(1, Point2DWithExtData.X); + Assert.Equal(2, Point2DWithExtData.Y); + Assert.True(Point2DWithExtData.ExtensionData.ContainsKey("b")); + + Assert.Equal(1, ReadOnlyPoint2DWithExtData.X); + Assert.Equal(2, ReadOnlyPoint2DWithExtData.Y); + Assert.True(ReadOnlyPoint2DWithExtData.ExtensionData.ContainsKey("b")); } public void VerifyMinimal() { - string serialized = JsonSerializer.Serialize(ReadOnlyPoint2D); - Assert.Contains(@"""X"":1", serialized); - Assert.Contains(@"""Y"":2", serialized); + ReadOnlyPoint2D.Verify(); } } @@ -802,53 +775,28 @@ public void Verify() Assert.Equal("f2c92fcc-459f-4287-90b6-a7cbd82aeb0e", Id.ToString()); Assert.Equal(24, Age); - string serialized = JsonSerializer.Serialize(this); - Assert.Contains(@"""Point2D"":{", serialized); - Assert.Contains(@"""ReadOnlyPoint2D"":{", serialized); - Assert.Contains(@"""Point2DWithExtDataClass"":{", serialized); - Assert.Contains(@"""ReadOnlyPoint2DWithExtDataClass"":{", serialized); - Assert.Contains(@"""Point3DStruct"":{", serialized); - Assert.Contains(@"""ReadOnlyPoint3DStruct"":{", serialized); - Assert.Contains(@"""Point2DWithExtData"":{", serialized); - Assert.Contains(@"""ReadOnlyPoint2DWithExtData"":{", serialized); + Point2D.Verify(); + ReadOnlyPoint2D.Verify(); - serialized = JsonSerializer.Serialize(Point2D); - Assert.Contains(@"""X"":1", serialized); - Assert.Contains(@"""Y"":2", serialized); + Assert.Equal(1, Point2DWithExtDataClass.X); + Assert.Equal(2, Point2DWithExtDataClass.Y); + Assert.True(Point2DWithExtDataClass.ExtensionData.ContainsKey("b")); - serialized = JsonSerializer.Serialize(ReadOnlyPoint2D); - Assert.Contains(@"""X"":1", serialized); - Assert.Contains(@"""Y"":2", serialized); + Assert.Equal(1, Point3DStruct.X); + Assert.Equal(2, Point3DStruct.Y); + Assert.Equal(3, Point3DStruct.Z); - serialized = JsonSerializer.Serialize(Point2DWithExtDataClass); - Assert.Contains(@"""X"":1", serialized); - Assert.Contains(@"""Y"":2", serialized); - Assert.Contains(@"""b"":3", serialized); + Assert.Equal(1, ReadOnlyPoint3DStruct.X); + Assert.Equal(2, ReadOnlyPoint3DStruct.Y); + Assert.Equal(3, ReadOnlyPoint3DStruct.Z); - serialized = JsonSerializer.Serialize(ReadOnlyPoint2DWithExtDataClass); - Assert.Contains(@"""X"":1", serialized); - Assert.Contains(@"""Y"":2", serialized); - Assert.Contains(@"""b"":3", serialized); + Assert.Equal(1, Point2DWithExtData.X); + Assert.Equal(2, Point2DWithExtData.Y); + Assert.True(Point2DWithExtData.ExtensionData.ContainsKey("b")); - serialized = JsonSerializer.Serialize(Point3DStruct); - Assert.Contains(@"""X"":1", serialized); - Assert.Contains(@"""Y"":2", serialized); - Assert.Contains(@"""Z"":3", serialized); - - serialized = JsonSerializer.Serialize(ReadOnlyPoint3DStruct); - Assert.Contains(@"""X"":1", serialized); - Assert.Contains(@"""Y"":2", serialized); - Assert.Contains(@"""Z"":3", serialized); - - serialized = JsonSerializer.Serialize(Point2DWithExtData); - Assert.Contains(@"""X"":1", serialized); - Assert.Contains(@"""Y"":2", serialized); - Assert.Contains(@"""b"":3", serialized); - - serialized = JsonSerializer.Serialize(ReadOnlyPoint2DWithExtData); - Assert.Contains(@"""X"":1", serialized); - Assert.Contains(@"""Y"":2", serialized); - Assert.Contains(@"""b"":3", serialized); + Assert.Equal(1, ReadOnlyPoint2DWithExtData.X); + Assert.Equal(2, ReadOnlyPoint2DWithExtData.Y); + Assert.True(ReadOnlyPoint2DWithExtData.ExtensionData.ContainsKey("b")); } } @@ -1014,7 +962,11 @@ public ObjWCtorMixedParams( } public static ObjWCtorMixedParams GetInstance() => +#if BUILDING_SOURCE_GENERATOR_TESTS + JsonSerializer.Deserialize(s_json, System.Text.Json.SourceGeneration.Tests.ConstructorTests_Default.ConstructorTestsContext_Default.Default.ObjWCtorMixedParams); +#else JsonSerializer.Deserialize(s_json); +#endif public static string s_json => $"{{{s_partialJson1},{s_partialJson2}}}"; @@ -2392,7 +2344,6 @@ public struct StructWithFourArgs public StructWithFourArgs(int w, int x, int y, int z) => (W, X, Y, Z) = (w, x, y, z); } -#if FIXED // https://github.com/dotnet/roslyn/issues/66900 public record ClassWithManyConstructorParameters( int P000, int P001, int P002, int P003, int P004, int P005, int P006, int P007, int P008, int P009, int P010, int P011, int P012, int P013, int P014, int P015, int P016, int P017, int P018, int P019, @@ -2600,5 +2551,4 @@ public static ClassWithManyConstructorParameters Create() P990: 990, P991: 991, P992: 992, P993: 993, P994: 994, P995: 995, P996: 996, P997: 997, P998: 998, P999: 999); } } -#endif } 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 3d7c500741102b..3a8a3b64c9fe43 100644 --- a/src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.cs +++ b/src/libraries/System.Text.Json/tests/Common/TestClasses/TestClasses.cs @@ -461,7 +461,11 @@ public void Verify() { if (data is JsonElement element) { - SimpleTestClass obj = JsonSerializer.Deserialize(element.GetRawText()); +#if BUILDING_SOURCE_GENERATOR_TESTS + SimpleTestClass obj = JsonSerializer.Deserialize(element, System.Text.Json.SourceGeneration.Tests.CollectionTests_Default.CollectionTestsContext_Default.Default.SimpleTestClass); +#else + SimpleTestClass obj = JsonSerializer.Deserialize(element); +#endif obj.Verify(); } else @@ -510,7 +514,11 @@ public void Verify() { if (data is JsonElement element) { - SimpleTestClass obj = JsonSerializer.Deserialize(element.GetRawText()); +#if BUILDING_SOURCE_GENERATOR_TESTS + SimpleTestClass obj = JsonSerializer.Deserialize(element, System.Text.Json.SourceGeneration.Tests.CollectionTests_Default.CollectionTestsContext_Default.Default.SimpleTestClass); +#else + SimpleTestClass obj = JsonSerializer.Deserialize(element); +#endif obj.Verify(); } else @@ -561,7 +569,11 @@ public void Verify() { if (data is JsonElement element) { - SimpleTestClass obj = JsonSerializer.Deserialize(element.GetRawText()); +#if BUILDING_SOURCE_GENERATOR_TESTS + SimpleTestClass obj = JsonSerializer.Deserialize(element, System.Text.Json.SourceGeneration.Tests.CollectionTests_Default.CollectionTestsContext_Default.Default.SimpleTestClass); +#else + SimpleTestClass obj = JsonSerializer.Deserialize(element); +#endif obj.Verify(); } else diff --git a/src/libraries/System.Text.Json/tests/Common/UnsupportedTypesTests.cs b/src/libraries/System.Text.Json/tests/Common/UnsupportedTypesTests.cs index df8850b277f456..a17831b43bd79a 100644 --- a/src/libraries/System.Text.Json/tests/Common/UnsupportedTypesTests.cs +++ b/src/libraries/System.Text.Json/tests/Common/UnsupportedTypesTests.cs @@ -27,6 +27,8 @@ public async Task DeserializeUnsupportedType(ValueWrapper wrapper) { _ = wrapper; // only used to instantiate T + Assert.NotNull(Serializer.GetTypeInfo(typeof(T))); // It should be possible to obtain metadata for the type. + string json = @"""Some string"""; // Any test payload is fine. Type type = GetNullableOfTUnderlyingType(typeof(T), out bool isNullableOfT); @@ -61,6 +63,8 @@ public async Task SerializeUnsupportedType(ValueWrapper wrapper) { T value = wrapper.value; + Assert.NotNull(Serializer.GetTypeInfo(typeof(T))); // It should be possible to obtain metadata for the type. + Type type = GetNullableOfTUnderlyingType(typeof(T), out bool isNullableOfT); string fullName = type.FullName; @@ -99,18 +103,19 @@ public async Task SerializeUnsupportedType(ValueWrapper wrapper) } #if !BUILDING_SOURCE_GENERATOR_TESTS - Type runtimeType = GetNullableOfTUnderlyingType(value.GetType(), out bool _); + // The reflection-based serializer will report the runtime type and not the declared type. + fullName = GetNullableOfTUnderlyingType(value.GetType(), out bool _).FullName; +#endif ex = await Assert.ThrowsAsync(async () => await Serializer.SerializeWrapper(value)); exAsStr = ex.ToString(); - Assert.Contains(runtimeType.FullName, exAsStr); + Assert.Contains(fullName, exAsStr); Assert.Contains("$", exAsStr); ClassWithType polyObj = new ClassWithType { Prop = value }; ex = await Assert.ThrowsAsync(async () => await Serializer.SerializeWrapper(polyObj)); exAsStr = ex.ToString(); - Assert.Contains(runtimeType.FullName, exAsStr); -#endif + Assert.Contains(fullName, exAsStr); } public static IEnumerable GetUnsupportedValues() @@ -124,6 +129,8 @@ public static IEnumerable GetUnsupportedValues() yield return WrapArgs((IntPtr)123); yield return WrapArgs(new IntPtr(123)); // One nullable variation. yield return WrapArgs((UIntPtr)123); + yield return WrapArgs((Memory)new byte[] { 1, 2, 3 }); + yield return WrapArgs((ReadOnlyMemory)new byte[] { 1, 2, 3 }); static object[] WrapArgs(T value) => new object[] { new ValueWrapper(value) }; } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/TestClasses.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/TestClasses.cs index a0eebf2e4fd383..4879565121d9ce 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/TestClasses.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.TestLibrary/TestClasses.cs @@ -10,6 +10,16 @@ public class MyPoco public string Value { get; set; } } + public class ClassFromOtherAssemblyWithNonPublicMembers + { + public int PublicValue { get; set; } = 1; + internal int InternalValue { get; set; } = 2; + private int PrivateValue { get; set; } = 4; + protected int ProtectedValue { get; set; } = 8; + private protected int PrivateProtectedValue { get; set; } = 16; + internal protected int InternalProtectedValue { get; set; } = 32; + } + [JsonSerializable(typeof(MyPoco))] public partial class NETStandardSerializerContext : JsonSerializerContext { 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 0d87b280c992a8..863d86bd5886f6 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 @@ -49,6 +49,8 @@ public interface ITestContext public JsonTypeInfo StructWithCustomConverterProperty { get; } public JsonTypeInfo ClassWithCustomConverterFactoryProperty { get; } public JsonTypeInfo StructWithCustomConverterFactoryProperty { get; } + public JsonTypeInfo ClassWithCustomConverterNullableProperty { get; } + public JsonTypeInfo ClassWithCustomConverterFactoryNullableProperty { get; } public JsonTypeInfo ClassWithBadCustomConverter { get; } public JsonTypeInfo StructWithBadCustomConverter { get; } public JsonTypeInfo NullablePersonStruct { get; } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs index a61ba2bc6a877f..9047bf03878474 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/JsonSerializerContextTests.cs @@ -6,6 +6,7 @@ using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; using System.Text.Json.Serialization.Tests; +using System.Text.Json.SourceGeneration.Tests.NETStandard; using System.Threading.Tasks; using Microsoft.DotNet.RemoteExecutor; using Xunit; @@ -125,12 +126,18 @@ public static async Task SupportsBoxedRootLevelValues() PersonJsonContext context = PersonJsonContext.Default; object person = new Person("John", "Smith"); string expectedJson = """{"firstName":"John","lastName":"Smith"}"""; - // Sanity check -- context does not specify object metadata - Assert.Null(context.GetTypeInfo(typeof(object))); + // Sanity check -- context resolver does not specify object metadata + Assert.Null(((IJsonTypeInfoResolver)context).GetTypeInfo(typeof(object), new())); string json = JsonSerializer.Serialize(person, context.Options); Assert.Equal(expectedJson, json); + json = JsonSerializer.Serialize(person, typeof(object), context); + Assert.Equal(expectedJson, json); + + json = JsonSerializer.Serialize(person, context.GetTypeInfo(typeof(object))); + Assert.NotNull(context.GetTypeInfo(typeof(object))); + var stream = new Utf8MemoryStream(); await JsonSerializer.SerializeAsync(stream, person, context.Options); Assert.Equal(expectedJson, stream.AsString()); @@ -698,19 +705,19 @@ internal partial class SingleClassWithCustomConverterFactoryPropertyContext : Js { } - // Regression test for https://github.com/dotnet/runtime/issues/61860 [Fact] public static void SupportsGenericParameterWithCustomConverterFactory() { + // Regression test for https://github.com/dotnet/runtime/issues/61860 var value = new List { TestEnum.Cee }; string json = JsonSerializer.Serialize(value, GenericParameterWithCustomConverterFactoryContext.Default.ListTestEnum); Assert.Equal(@"[""Cee""]", json); } - // Regression test for https://github.com/dotnet/runtime/issues/74652 [Fact] public static void ClassWithStringValuesRoundtrips() { + // Regression test for https://github.com/dotnet/runtime/issues/74652 JsonSerializerOptions options = ClassWithStringValuesContext.Default.Options; ClassWithStringValues obj = new() @@ -722,10 +729,10 @@ public static void ClassWithStringValuesRoundtrips() Assert.Equal("""{"StringValuesProperty":["abc","def"]}""", json); } - // Regression test for https://github.com/dotnet/runtime/issues/61734 [Fact] public static void ClassWithDictionaryPropertyRoundtrips() { + // Regression test for https://github.com/dotnet/runtime/issues/61734 JsonSerializerOptions options = ClassWithDictionaryPropertyContext.Default.Options; ClassWithDictionaryProperty obj = new(new Dictionary() @@ -738,7 +745,7 @@ public static void ClassWithDictionaryPropertyRoundtrips() Assert.Equal("""{"DictionaryProperty":{"foo":"bar","test":"baz"}}""", json); } - [JsonConverter(typeof(JsonStringEnumConverter))] + [JsonConverter(typeof(JsonStringEnumConverter))] public enum TestEnum { Aye, Bee, Cee @@ -764,6 +771,26 @@ internal partial class ClassWithDictionaryPropertyContext : JsonSerializerContex { } + [Fact] + public static void DoesNotReferenceInternalMembersFromOtherAssemblies() + { + // Regression test for https://github.com/dotnet/runtime/issues/66679 + + Assert.Equal(1, ContextForClassesFromAnotherAssembly.Default.ClassFromOtherAssemblyWithNonPublicMembers.Properties.Count); + Assert.Equal("PublicValue", ContextForClassesFromAnotherAssembly.Default.ClassFromOtherAssemblyWithNonPublicMembers.Properties[0].Name); + + var value = new ClassFromOtherAssemblyWithNonPublicMembers(); + string json = JsonSerializer.Serialize(value, ContextForClassesFromAnotherAssembly.Default.ClassFromOtherAssemblyWithNonPublicMembers); + Assert.Equal("""{"PublicValue":1}""", json); + + JsonSerializer.Deserialize(json, ContextForClassesFromAnotherAssembly.Default.ClassFromOtherAssemblyWithNonPublicMembers); + } + + [JsonSerializable(typeof(ClassFromOtherAssemblyWithNonPublicMembers))] + internal partial class ContextForClassesFromAnotherAssembly : JsonSerializerContext + { + } + internal class ClassWithPocoListDictionaryAndNullable { public uint UIntProperty { get; set; } 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 8e37e934f7c34c..8ebf4c2e7f7c86 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 @@ -45,6 +45,8 @@ namespace System.Text.Json.SourceGeneration.Tests [JsonSerializable(typeof(StructWithCustomConverterProperty))] [JsonSerializable(typeof(ClassWithCustomConverterFactoryProperty))] [JsonSerializable(typeof(StructWithCustomConverterFactoryProperty))] + [JsonSerializable(typeof(ClassWithCustomConverterNullableProperty))] + [JsonSerializable(typeof(ClassWithCustomConverterFactoryNullableProperty))] [JsonSerializable(typeof(ClassWithBadCustomConverter))] [JsonSerializable(typeof(StructWithBadCustomConverter))] [JsonSerializable(typeof(PersonStruct?))] 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 4cb83945fabf76..5100371cd9c86c 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 @@ -44,6 +44,8 @@ namespace System.Text.Json.SourceGeneration.Tests [JsonSerializable(typeof(StructWithCustomConverterProperty), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(ClassWithCustomConverterFactoryProperty), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(StructWithCustomConverterFactoryProperty), GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof(ClassWithCustomConverterNullableProperty), GenerationMode = JsonSourceGenerationMode.Metadata)] + [JsonSerializable(typeof(ClassWithCustomConverterFactoryNullableProperty), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(ClassWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(StructWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(PersonStruct?), GenerationMode = JsonSourceGenerationMode.Metadata)] @@ -144,6 +146,8 @@ public override void EnsureFastPathGeneratedAsExpected() [JsonSerializable(typeof(StructWithCustomConverterProperty))] [JsonSerializable(typeof(ClassWithCustomConverterFactoryProperty))] [JsonSerializable(typeof(StructWithCustomConverterFactoryProperty))] + [JsonSerializable(typeof(ClassWithCustomConverterNullableProperty))] + [JsonSerializable(typeof(ClassWithCustomConverterFactoryNullableProperty))] [JsonSerializable(typeof(ClassWithBadCustomConverter))] [JsonSerializable(typeof(StructWithBadCustomConverter))] [JsonSerializable(typeof(PersonStruct?))] @@ -156,7 +160,7 @@ internal partial class MetadataContext : JsonSerializerContext, ITestContext public bool IsIncludeFieldsEnabled => GetType().GetCustomAttribute()?.IncludeFields ?? false; } - [JsonConverter(typeof(JsonStringEnumConverter))] + [JsonConverter(typeof(JsonStringEnumConverter))] public enum EnumWrittenAsString { A = 1 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 98d3dfa3bd5693..bd5a5256f663e5 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 @@ -45,6 +45,8 @@ namespace System.Text.Json.SourceGeneration.Tests [JsonSerializable(typeof(StructWithCustomConverterProperty), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(ClassWithCustomConverterFactoryProperty), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(StructWithCustomConverterFactoryProperty), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithCustomConverterNullableProperty), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithCustomConverterFactoryNullableProperty), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(ClassWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(StructWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Metadata | JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(PersonStruct?), 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 1d482e1cd82233..d0cef8311b67e9 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 @@ -6,7 +6,6 @@ using System.Linq; using System.Text.Json.Serialization; using System.Text.Json.Serialization.Metadata; -using System.Text.Json.Serialization.Tests; using Xunit; namespace System.Text.Json.SourceGeneration.Tests @@ -257,6 +256,60 @@ public virtual void RoundtripWithCustomConverterProperty_Class() Assert.Equal(42, obj.Property.Value); } + [Fact] + public virtual void RoundTripWithCustomConverterNullableProperty() + { + const string Json = "{\"TimeSpan\":42}"; + + var obj = new ClassWithCustomConverterNullableProperty + { + TimeSpan = TimeSpan.FromSeconds(42) + }; + + // Types with properties in custom converters do not support fast path serialization. + Assert.True(DefaultContext.ClassWithCustomConverterNullableProperty.SerializeHandler is null); + + if (DefaultContext.JsonSourceGenerationMode == JsonSourceGenerationMode.Serialization) + { + Assert.Throws(() => JsonSerializer.Serialize(obj, DefaultContext.ClassWithCustomConverterNullableProperty)); + } + else + { + string json = JsonSerializer.Serialize(obj, DefaultContext.ClassWithCustomConverterNullableProperty); + Assert.Equal(Json, json); + + obj = JsonSerializer.Deserialize(Json, DefaultContext.ClassWithCustomConverterNullableProperty); + Assert.Equal(42, obj.TimeSpan.Value.TotalSeconds); + } + } + + [Fact] + public virtual void RoundTripWithCustomConverterFactoryNullableProperty() + { + const string Json = "{\"MyEnum\":\"Two\"}"; + + var obj = new ClassWithCustomConverterFactoryNullableProperty + { + MyEnum = SourceGenSampleEnum.Two + }; + + // Types with properties in custom converters do not support fast path serialization. + Assert.True(DefaultContext.ClassWithCustomConverterFactoryNullableProperty.SerializeHandler is null); + + if (DefaultContext.JsonSourceGenerationMode == JsonSourceGenerationMode.Serialization) + { + Assert.Throws(() => JsonSerializer.Serialize(obj, DefaultContext.ClassWithCustomConverterFactoryNullableProperty)); + } + else + { + string json = JsonSerializer.Serialize(obj, DefaultContext.ClassWithCustomConverterFactoryNullableProperty); + Assert.Equal(Json, json); + + obj = JsonSerializer.Deserialize(Json, DefaultContext.ClassWithCustomConverterFactoryNullableProperty); + Assert.Equal(SourceGenSampleEnum.Two, obj.MyEnum.Value); + } + } + [Fact] public virtual void RoundtripWithCustomConverterProperty_Struct() { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/CollectionTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/CollectionTests.cs index 1f82adaae84cca..a9b785a47fb617 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/CollectionTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/CollectionTests.cs @@ -343,16 +343,31 @@ public async Task DeserializeAsyncEnumerable() [JsonSerializable(typeof(StringIImmutableSetWrapper))] [JsonSerializable(typeof(IEnumerable))] [JsonSerializable(typeof(ICollection>))] + [JsonSerializable(typeof(IEnumerable))] + [JsonSerializable(typeof(IEnumerable))] + [JsonSerializable(typeof(IEnumerable))] + [JsonSerializable(typeof(IEnumerable>))] + [JsonSerializable(typeof(IEnumerable>))] + [JsonSerializable(typeof(IEnumerable>))] + [JsonSerializable(typeof((IEnumerable, bool)?))] + [JsonSerializable(typeof((IEnumerable, bool)?))] + [JsonSerializable(typeof((IEnumerable, bool)?))] [JsonSerializable(typeof(IAsyncEnumerable))] [JsonSerializable(typeof(IAsyncEnumerable))] [JsonSerializable(typeof(IAsyncEnumerable))] + [JsonSerializable(typeof(EnumerableDto))] + [JsonSerializable(typeof(EnumerableDto))] + [JsonSerializable(typeof(EnumerableDto))] [JsonSerializable(typeof(AsyncEnumerableDto))] [JsonSerializable(typeof(AsyncEnumerableDto))] [JsonSerializable(typeof(AsyncEnumerableDto))] + [JsonSerializable(typeof(AsyncEnumerableDto>))] + [JsonSerializable(typeof(EnumerableDtoWithTwoProperties))] + [JsonSerializable(typeof(EnumerableDtoWithTwoProperties))] + [JsonSerializable(typeof(EnumerableDtoWithTwoProperties))] [JsonSerializable(typeof(AsyncEnumerableDtoWithTwoProperties))] [JsonSerializable(typeof(AsyncEnumerableDtoWithTwoProperties))] [JsonSerializable(typeof(AsyncEnumerableDtoWithTwoProperties))] - [JsonSerializable(typeof(AsyncEnumerableDto>))] [JsonSerializable(typeof(MockedAsyncEnumerable))] [JsonSerializable(typeof(MockedAsyncEnumerable))] [JsonSerializable(typeof(MockedAsyncEnumerable))] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ConstructorTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ConstructorTests.cs index 2b4a718dec4df9..b2a5fd465da766 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ConstructorTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ConstructorTests.cs @@ -141,13 +141,15 @@ protected ConstructorTests_Metadata(JsonSerializerWrapper stringWrapper) [JsonSerializable(typeof(LargeType_IgnoredProp_Bind_Param))] [JsonSerializable(typeof(ClassWithIgnoredSameType))] [JsonSerializable(typeof(ClassWithDefaultCtorParams))] -#if FIXED // https://github.com/dotnet/roslyn/issues/66900 + [JsonSerializable(typeof(StructWithPropertyInit))] + [JsonSerializable(typeof(StructWithFieldInit))] + [JsonSerializable(typeof(StructWithExplicitParameterlessCtor))] [JsonSerializable(typeof(ClassWithManyConstructorParameters))] -#endif [JsonSerializable(typeof(ClassWithInvalidArray))] [JsonSerializable(typeof(ClassWithInvalidDictionary))] [JsonSerializable(typeof(TypeWithEnumParameters))] [JsonSerializable(typeof(ClassWithIgnoredPropertyDefaultParam))] + [JsonSerializable(typeof(ClassWithCustomConverterOnCtorParameter))] internal sealed partial class ConstructorTestsContext_Metadata : JsonSerializerContext { } @@ -284,13 +286,15 @@ public ConstructorTests_Default(JsonSerializerWrapper jsonSerializer) : base(jso [JsonSerializable(typeof(LargeType_IgnoredProp_Bind_Param))] [JsonSerializable(typeof(ClassWithIgnoredSameType))] [JsonSerializable(typeof(ClassWithDefaultCtorParams))] -#if FIXED // https://github.com/dotnet/roslyn/issues/66900 + [JsonSerializable(typeof(StructWithPropertyInit))] + [JsonSerializable(typeof(StructWithFieldInit))] + [JsonSerializable(typeof(StructWithExplicitParameterlessCtor))] [JsonSerializable(typeof(ClassWithManyConstructorParameters))] -#endif [JsonSerializable(typeof(ClassWithInvalidArray))] [JsonSerializable(typeof(ClassWithInvalidDictionary))] [JsonSerializable(typeof(TypeWithEnumParameters))] [JsonSerializable(typeof(ClassWithIgnoredPropertyDefaultParam))] + [JsonSerializable(typeof(ClassWithCustomConverterOnCtorParameter))] internal sealed partial class ConstructorTestsContext_Default : JsonSerializerContext { } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ExtensionDataTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ExtensionDataTests.cs index 6d5d8982145e13..ba67748368ff3b 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ExtensionDataTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/ExtensionDataTests.cs @@ -61,6 +61,10 @@ public ExtensionDataTests_Metadata() [JsonSerializable(typeof(ClassWithExtensionPropertyThreeGenericParameters))] [JsonSerializable(typeof(JsonElement))] [JsonSerializable(typeof(ClassWithExtensionData))] + [JsonSerializable(typeof(ClassWithExtensionData>))] + [JsonSerializable(typeof(ClassWithExtensionData>))] + [JsonSerializable(typeof(ClassWithExtensionData>))] + [JsonSerializable(typeof(ClassWithExtensionData>))] [JsonSerializable(typeof(int))] [JsonSerializable(typeof(DummyObj))] [JsonSerializable(typeof(DummyStruct))] @@ -121,6 +125,10 @@ public ExtensionDataTests_Default() [JsonSerializable(typeof(ClassWithExtensionPropertyThreeGenericParameters))] [JsonSerializable(typeof(JsonElement))] [JsonSerializable(typeof(ClassWithExtensionData))] + [JsonSerializable(typeof(ClassWithExtensionData>))] + [JsonSerializable(typeof(ClassWithExtensionData>))] + [JsonSerializable(typeof(ClassWithExtensionData>))] + [JsonSerializable(typeof(ClassWithExtensionData>))] [JsonSerializable(typeof(int))] [JsonSerializable(typeof(DummyObj))] [JsonSerializable(typeof(DummyStruct))] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs index 3c15522874cfb3..aae3ab143948ad 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/PropertyVisibilityTests.cs @@ -145,6 +145,32 @@ public override async Task HonorJsonPropertyName_PrivateSetter() Assert.Equal(json, await Serializer.SerializeWrapper(obj)); } + [Fact] + public override async Task TestCollectionWithPrivateElementType() + { + // The source generator cannot support enumerables whose element type is private. + CollectionWithPrivateElementType collection = CollectionWithPrivateElementType.CreatePopulatedInstance(); + string json = collection.GetExpectedJson(); + + Assert.True(Serializer.DefaultOptions.TryGetTypeInfo(typeof(CollectionWithPrivateElementType), out _)); + + await Assert.ThrowsAsync(() => Serializer.SerializeWrapper(collection)); + await Assert.ThrowsAsync(() => Serializer.DeserializeWrapper(json)); + } + + [Fact] + public override async Task TestDictionaryWithPrivateKeyAndValueType() + { + // The source generator cannot support dictionaries whose key/value types are private. + DictionaryWithPrivateKeyAndValueType dictionary = DictionaryWithPrivateKeyAndValueType.CreatePopulatedInstance(); + string json = dictionary.GetExpectedJson(); + + Assert.True(Serializer.DefaultOptions.TryGetTypeInfo(typeof(DictionaryWithPrivateKeyAndValueType), out _)); + + await Assert.ThrowsAsync(() => Serializer.SerializeWrapper(dictionary)); + await Assert.ThrowsAsync(() => Serializer.DeserializeWrapper(json)); + } + [JsonSourceGenerationOptions(GenerationMode = JsonSourceGenerationMode.Metadata)] [JsonSerializable(typeof(ClassWithNewSlotField))] [JsonSerializable(typeof(int))] @@ -174,6 +200,7 @@ public override async Task HonorJsonPropertyName_PrivateSetter() [JsonSerializable(typeof(Class_PropertyWith_ProtectedInitOnlySetter))] [JsonSerializable(typeof(ClassWithIgnoredPublicProperty))] [JsonSerializable(typeof(ClassWithIgnoredPublicPropertyAndNewSlotPrivate))] + [JsonSerializable(typeof(ClassWithIgnoredPublicPropertyAndNewSlotPublicAndIgnoredToo))] [JsonSerializable(typeof(ClassWithIgnoredPropertyPolicyConflictPublic))] [JsonSerializable(typeof(ClassWithIgnoredPropertyNamingConflictPrivate))] [JsonSerializable(typeof(ClassWithIgnoredNewSlotProperty))] @@ -183,6 +210,15 @@ public override async Task HonorJsonPropertyName_PrivateSetter() [JsonSerializable(typeof(ClassWithNewSlotInternalProperty))] [JsonSerializable(typeof(ClassWithPropertyPolicyConflict))] [JsonSerializable(typeof(ClassWithPrivateSetterAndGetter))] + [JsonSerializable(typeof(ClassWithProtectedMembers))] + [JsonSerializable(typeof(ClassWithProtectedGetter))] + [JsonSerializable(typeof(ClassWithProtectedSetter))] + [JsonSerializable(typeof(ClassWithPrivateProtectedMembers))] + [JsonSerializable(typeof(ClassWithPrivateProtectedGetter))] + [JsonSerializable(typeof(ClassWithPrivateProtectedSetter))] + [JsonSerializable(typeof(ClassWithInternalProtectedMembers))] + [JsonSerializable(typeof(ClassWithInternalProtectedGetter))] + [JsonSerializable(typeof(ClassWithInternalProtectedSetter))] [JsonSerializable(typeof(ClassWithIgnoreAttributeProperty))] [JsonSerializable(typeof(ClassWithIgnoredNewSlotField))] [JsonSerializable(typeof(MyStruct_WithNonPublicAccessors_WithTypeAttribute))] @@ -283,6 +319,8 @@ public override async Task HonorJsonPropertyName_PrivateSetter() [JsonSerializable(typeof(IDiamondInterfaceHierarchy.IJoinInterface))] [JsonSerializable(typeof(IDiamondInterfaceHierarchyWithNamingConflict.IJoinInterface), TypeInfoPropertyName = "IDiamondInterfaceHierarchyWithNamingConflictIJoinInterface")] [JsonSerializable(typeof(IDiamondInterfaceHierarchyWithNamingConflictUsingAttribute.IJoinInterface), TypeInfoPropertyName = "IDiamondInterfaceHierarchyWithNamingConflictUsingAttributeIJoinInterface")] + [JsonSerializable(typeof(CollectionWithPrivateElementType))] + [JsonSerializable(typeof(DictionaryWithPrivateKeyAndValueType))] internal sealed partial class PropertyVisibilityTestsContext_Metadata : JsonSerializerContext { } @@ -419,6 +457,7 @@ public void PublicContextAndJsonSerializerOptions() [JsonSerializable(typeof(Class_PropertyWith_ProtectedInitOnlySetter))] [JsonSerializable(typeof(ClassWithIgnoredPublicProperty))] [JsonSerializable(typeof(ClassWithIgnoredPublicPropertyAndNewSlotPrivate))] + [JsonSerializable(typeof(ClassWithIgnoredPublicPropertyAndNewSlotPublicAndIgnoredToo))] [JsonSerializable(typeof(ClassWithIgnoredPropertyPolicyConflictPublic))] [JsonSerializable(typeof(ClassWithIgnoredPropertyNamingConflictPrivate))] [JsonSerializable(typeof(ClassWithIgnoredNewSlotProperty))] @@ -428,6 +467,15 @@ public void PublicContextAndJsonSerializerOptions() [JsonSerializable(typeof(ClassWithNewSlotInternalProperty))] [JsonSerializable(typeof(ClassWithPropertyPolicyConflict))] [JsonSerializable(typeof(ClassWithPrivateSetterAndGetter))] + [JsonSerializable(typeof(ClassWithProtectedMembers))] + [JsonSerializable(typeof(ClassWithProtectedGetter))] + [JsonSerializable(typeof(ClassWithProtectedSetter))] + [JsonSerializable(typeof(ClassWithPrivateProtectedMembers))] + [JsonSerializable(typeof(ClassWithPrivateProtectedGetter))] + [JsonSerializable(typeof(ClassWithPrivateProtectedSetter))] + [JsonSerializable(typeof(ClassWithInternalProtectedMembers))] + [JsonSerializable(typeof(ClassWithInternalProtectedGetter))] + [JsonSerializable(typeof(ClassWithInternalProtectedSetter))] [JsonSerializable(typeof(ClassWithIgnoreAttributeProperty))] [JsonSerializable(typeof(ClassWithIgnoredNewSlotField))] [JsonSerializable(typeof(MyStruct_WithNonPublicAccessors_WithTypeAttribute))] @@ -528,6 +576,8 @@ public void PublicContextAndJsonSerializerOptions() [JsonSerializable(typeof(IDiamondInterfaceHierarchy.IJoinInterface))] [JsonSerializable(typeof(IDiamondInterfaceHierarchyWithNamingConflict.IJoinInterface), TypeInfoPropertyName = "IDiamondInterfaceHierarchyWithNamingConflictIJoinInterface")] [JsonSerializable(typeof(IDiamondInterfaceHierarchyWithNamingConflictUsingAttribute.IJoinInterface), TypeInfoPropertyName = "IDiamondInterfaceHierarchyWithNamingConflictUsingAttributeIJoinInterface")] + [JsonSerializable(typeof(CollectionWithPrivateElementType))] + [JsonSerializable(typeof(DictionaryWithPrivateKeyAndValueType))] internal sealed partial class PropertyVisibilityTestsContext_Default : JsonSerializerContext { } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/UnsupportedTypesTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/UnsupportedTypesTests.cs index 8dc14d3d2badf9..6220538d5b52d0 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/UnsupportedTypesTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/Serialization/UnsupportedTypesTests.cs @@ -23,6 +23,7 @@ public UnsupportedTypesTests_Metadata() : base( [JsonSerializable(typeof(ClassWithIntPtrConverter))] // Unsupported types: [JsonSerializable(typeof(Type))] + [JsonSerializable(typeof(ClassWithType))] [JsonSerializable(typeof(ClassWithType))] [JsonSerializable(typeof(ConstructorInfo))] [JsonSerializable(typeof(ClassWithType))] @@ -41,6 +42,10 @@ public UnsupportedTypesTests_Metadata() : base( [JsonSerializable(typeof(ClassWithType))] [JsonSerializable(typeof(UIntPtr))] [JsonSerializable(typeof(ClassWithType))] + [JsonSerializable(typeof(Memory))] + [JsonSerializable(typeof(ClassWithType>))] + [JsonSerializable(typeof(ReadOnlyMemory))] + [JsonSerializable(typeof(ClassWithType>))] [JsonSerializable(typeof(IAsyncEnumerable))] [JsonSerializable(typeof(ClassWithType>))] [JsonSerializable(typeof(ClassThatImplementsIAsyncEnumerable))] @@ -64,6 +69,7 @@ public UnsupportedTypesTests_Default() : base( [JsonSerializable(typeof(ClassWithIntPtrConverter))] // Unsupported types: [JsonSerializable(typeof(Type))] + [JsonSerializable(typeof(ClassWithType))] [JsonSerializable(typeof(ClassWithType))] [JsonSerializable(typeof(ConstructorInfo))] [JsonSerializable(typeof(ClassWithType))] @@ -82,6 +88,10 @@ public UnsupportedTypesTests_Default() : base( [JsonSerializable(typeof(ClassWithType))] [JsonSerializable(typeof(UIntPtr))] [JsonSerializable(typeof(ClassWithType))] + [JsonSerializable(typeof(Memory))] + [JsonSerializable(typeof(ClassWithType>))] + [JsonSerializable(typeof(ReadOnlyMemory))] + [JsonSerializable(typeof(ClassWithType>))] [JsonSerializable(typeof(IAsyncEnumerable))] [JsonSerializable(typeof(ClassWithType>))] [JsonSerializable(typeof(ClassThatImplementsIAsyncEnumerable))] 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 837e896d5be758..4ff2b9033513c1 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 @@ -46,6 +46,8 @@ namespace System.Text.Json.SourceGeneration.Tests [JsonSerializable(typeof(StructWithCustomConverterProperty))] [JsonSerializable(typeof(ClassWithCustomConverterFactoryProperty))] [JsonSerializable(typeof(StructWithCustomConverterFactoryProperty))] + [JsonSerializable(typeof(ClassWithCustomConverterNullableProperty))] + [JsonSerializable(typeof(ClassWithCustomConverterFactoryNullableProperty))] [JsonSerializable(typeof(ClassWithBadCustomConverter))] [JsonSerializable(typeof(StructWithBadCustomConverter))] [JsonSerializable(typeof(PersonStruct?))] @@ -95,6 +97,8 @@ internal partial class SerializationContext : JsonSerializerContext, ITestContex [JsonSerializable(typeof(StructWithCustomConverterProperty), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(ClassWithCustomConverterFactoryProperty), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(StructWithCustomConverterFactoryProperty), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithCustomConverterNullableProperty), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithCustomConverterFactoryNullableProperty), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(ClassWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(StructWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(PersonStruct?), GenerationMode = JsonSourceGenerationMode.Serialization)] @@ -145,6 +149,8 @@ internal partial class SerializationWithPerTypeAttributeContext : JsonSerializer [JsonSerializable(typeof(StructWithCustomConverterProperty), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(ClassWithCustomConverterFactoryProperty), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(StructWithCustomConverterFactoryProperty), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithCustomConverterNullableProperty), GenerationMode = JsonSourceGenerationMode.Serialization)] + [JsonSerializable(typeof(ClassWithCustomConverterFactoryNullableProperty), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(ClassWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(StructWithBadCustomConverter), GenerationMode = JsonSourceGenerationMode.Serialization)] [JsonSerializable(typeof(PersonStruct?), GenerationMode = JsonSourceGenerationMode.Serialization)] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Roslyn3.11.Tests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Roslyn3.11.Tests.csproj index 378fb96ca49f11..bde7513156c634 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Roslyn3.11.Tests.csproj +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Roslyn3.11.Tests.csproj @@ -6,6 +6,10 @@ + + + + diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Roslyn4.4.Tests.csproj b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Roslyn4.4.Tests.csproj index 5d327473bd433e..0fa1bccdb970ba 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Roslyn4.4.Tests.csproj +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Roslyn4.4.Tests.csproj @@ -11,6 +11,10 @@ + + + + diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets index 6c5d287ca786b3..704790d353f3dd 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/System.Text.Json.SourceGeneration.Tests.targets @@ -8,7 +8,8 @@ - $(NoWarn);SYSLIB0020;SYSLIB0049;SYSLIB1037;SYSLIB1038;SYSLIB1039 + + $(NoWarn);SYSLIB0020;SYSLIB0049;SYSLIB1037;SYSLIB1038;SYSLIB1039;SYSLIB1040 true diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/TestClasses.CustomConverters.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/TestClasses.CustomConverters.cs index 18762d22bcee30..0a4ac1a1904129 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/TestClasses.CustomConverters.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/TestClasses.CustomConverters.cs @@ -247,16 +247,41 @@ public struct StructWithCustomConverterProperty public class ClassWithCustomConverterFactoryProperty { - [JsonConverter(typeof(JsonStringEnumConverter))] // This converter is a JsonConverterFactory + [JsonConverter(typeof(JsonStringEnumConverter))] // This converter is a JsonConverterFactory public SourceGenSampleEnum MyEnum { get; set; } } public struct StructWithCustomConverterFactoryProperty { - [JsonConverter(typeof(JsonStringEnumConverter))] // This converter is a JsonConverterFactory + [JsonConverter(typeof(JsonStringEnumConverter))] // This converter is a JsonConverterFactory public SourceGenSampleEnum MyEnum { get; set; } } + public class ClassWithCustomConverterFactoryNullableProperty + { + [JsonConverter(typeof(JsonStringEnumConverter))] // This converter is a JsonConverterFactory + public SourceGenSampleEnum? MyEnum { get; set; } + } + + public class ClassWithCustomConverterNullableProperty + { + [JsonConverter(typeof(TimeSpanSecondsConverter))] + public TimeSpan? TimeSpan { get; set; } + } + + public class TimeSpanSecondsConverter : JsonConverter + { + public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + return TimeSpan.FromSeconds(reader.GetDouble()); + } + + public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options) + { + writer.WriteNumberValue(value.TotalSeconds); + } + } + [JsonConverter(typeof(CustomConverter_StructWithCustomConverter))] // Invalid public class ClassWithBadCustomConverter { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/roslyn3.11.rd.xml b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/roslyn3.11.rd.xml new file mode 100644 index 00000000000000..eedb1e4ecc710f --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/roslyn3.11.rd.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/roslyn4.4.rd.xml b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/roslyn4.4.rd.xml new file mode 100644 index 00000000000000..f9656b2e23382f --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Tests/roslyn4.4.rd.xml @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 66a55a42ea3a25..dca62396a25988 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 @@ -483,6 +483,13 @@ namespace HelloWorld { public class Location { + [JsonInclude] + public int publicField; + [JsonInclude] + internal int internalField; + [JsonInclude] + private int privateField; + [JsonInclude] public int Id { get; private set; } [JsonInclude] @@ -610,40 +617,60 @@ public class MyDerivedClass : MyBaseClass return CreateCompilation(source); } - internal static void CheckDiagnosticMessages( - DiagnosticSeverity level, - ImmutableArray diagnostics, - (Location Location, string Message)[] expectedDiags, - bool sort = true) + public static Compilation CreateTypesAnnotatedWithJsonStringEnumConverter() { - ((string FileName, TextSpan, LinePositionSpan), string)[] actualDiags = diagnostics - .Where(diagnostic => diagnostic.Severity == level) - .Select(diagnostic => (GetLocationNormalForm(diagnostic.Location), diagnostic.GetMessage())) - .ToArray(); - - if (CultureInfo.CurrentUICulture.Name.StartsWith("en", StringComparison.OrdinalIgnoreCase)) - { - ((string FileName, TextSpan, LinePositionSpan), string Message)[] expectedDiagsNormalized = expectedDiags - .Select(diag => (GetLocationNormalForm(diag.Location), diag.Message)) - .ToArray(); + string source = """ + using System.Text.Json.Serialization; - if (sort) + namespace HelloWorld { - // Can't depend on reflection order when generating type metadata. - Array.Sort(actualDiags); - Array.Sort(expectedDiagsNormalized); + [JsonSerializable(typeof(MyClass))] + internal partial class JsonContext : JsonSerializerContext + { + } + + public class MyClass + { + public Enum1 Enum1Prop { get; set; } + + [JsonConverter(typeof(JsonStringEnumConverter))] + public Enum2 Enum2Prop { get; set; } + } + + [JsonConverter(typeof(JsonStringEnumConverter))] + public enum Enum1 { A, B, C }; + + public enum Enum2 { A, B, C }; } + """; - Assert.Equal(expectedDiagsNormalized, actualDiags); - } - else - { - // for non-English runs, just compare the number of messages are the same - Assert.Equal(expectedDiags.Length, actualDiags.Length); - } + return CreateCompilation(source); + } + + internal static void AssertEqualDiagnosticMessages( + IEnumerable expectedDiags, + IEnumerable actualDiags) + { + HashSet expectedSet = new(expectedDiags); + HashSet actualSet = new(actualDiags.Select(d => new DiagnosticData(d.Severity, d.Location, d.GetMessage()))); + AssertExtensions.Equal(expectedSet, actualSet); + } + } - static (string FileName, TextSpan, LinePositionSpan) GetLocationNormalForm(Location location) - => (location.SourceTree?.FilePath ?? "", location.SourceSpan, location.GetLineSpan().Span); + public record struct DiagnosticData( + DiagnosticSeverity Severity, + string FilePath, + LinePositionSpan LinePositionSpan, + string Message) + { + public DiagnosticData(DiagnosticSeverity severity, Location location, string message) + : this(severity, location.SourceTree?.FilePath ?? "", location.GetLineSpan().Span, TrimCultureSensitiveMessage(message)) + { } + + // for non-English runs, trim the message content since it might be translated. + private static string TrimCultureSensitiveMessage(string message) => s_IsEnglishCulture ? message : ""; + private readonly static bool s_IsEnglishCulture = CultureInfo.CurrentUICulture.Name.StartsWith("en", StringComparison.OrdinalIgnoreCase); + public override string ToString() => $"{Severity}, {Message}, {FilePath}@{LinePositionSpan}"; } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorDiagnosticsTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorDiagnosticsTests.cs index 785906bb29c240..fcc219564e5209 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorDiagnosticsTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.SourceGeneration.Unit.Tests/JsonSourceGeneratorDiagnosticsTests.cs @@ -79,11 +79,8 @@ public class DocumentedModel using var emitStream = new MemoryStream(); using var xmlStream = new MemoryStream(); var result = sourceGenResult.NewCompilation.Emit(emitStream, xmlDocumentationStream: xmlStream); - var diagnostics = result.Diagnostics; - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, diagnostics, Array.Empty<(Location, string)>()); + Assert.Empty(result.Diagnostics); } [Fact] @@ -129,9 +126,7 @@ public class IndexViewModel JsonSourceGeneratorResult result = CompilationHelper.RunJsonSourceGenerator(compilation); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, result.Diagnostics, Array.Empty<(Location, string)>()); + Assert.Empty(result.Diagnostics); } [Fact] @@ -174,32 +169,13 @@ public class IndexViewModel """; MetadataReference[] additionalReferences = { - MetadataReference.CreateFromImage(campaignImage), - MetadataReference.CreateFromImage(eventImage), - }; + MetadataReference.CreateFromImage(campaignImage), + MetadataReference.CreateFromImage(eventImage), + }; Compilation compilation = CompilationHelper.CreateCompilation(source, additionalReferences); - JsonSourceGeneratorResult result = CompilationHelper.RunJsonSourceGenerator(compilation); - - Location location; - if (explicitRef) - { - // Unsupported type is not in compiling assembly, but is indicated directly with [JsonSerializable], so location points to attribute application. - INamedTypeSymbol symbol = (INamedTypeSymbol)compilation.GetSymbolsWithName("JsonContext").FirstOrDefault(); - SyntaxReference syntaxReference = symbol.GetAttributes().First().ApplicationSyntaxReference; - TextSpan textSpan = syntaxReference.Span; - location = syntaxReference.SyntaxTree.GetLocation(textSpan)!; - } - else - { - // Unsupported type is not in compiling assembly, and isn't indicated directly with [JsonSerializable], so location points to context type. - location = compilation.GetSymbolsWithName("JsonContext").First().Locations[0]; - } - - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, result.Diagnostics, Array.Empty<(Location, string)>()); + Assert.Empty(result.Diagnostics); } RunTest(explicitRef: true); @@ -218,22 +194,18 @@ public void NameClashSourceGeneration() TextSpan textSpan = syntaxReference.Span; Location location = syntaxReference.SyntaxTree.GetLocation(textSpan)!; - (Location, string)[] expectedWarningDiagnostics = new (Location, string)[] + var expectedDiagnostics = new DiagnosticData[] { - (location, "There are multiple types named Location. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.") + new(DiagnosticSeverity.Warning, location, "There are multiple types named Location. Source was generated for the first one detected. Use 'JsonSerializableAttribute.TypeInfoPropertyName' to resolve this collision.") }; - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, result.Diagnostics, expectedWarningDiagnostics); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, result.Diagnostics, Array.Empty<(Location, string)>()); + CompilationHelper.AssertEqualDiagnosticMessages(expectedDiagnostics, result.Diagnostics); // With resolution. compilation = CompilationHelper.CreateRepeatedLocationsWithResolutionCompilation(); result = CompilationHelper.RunJsonSourceGenerator(compilation); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, result.Diagnostics, Array.Empty<(Location, string)>()); + Assert.Empty(result.Diagnostics); } [Fact] @@ -255,9 +227,7 @@ public static void Main() Compilation compilation = CompilationHelper.CreateCompilation(source); JsonSourceGeneratorResult result = CompilationHelper.RunJsonSourceGenerator(compilation); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, result.Diagnostics, Array.Empty<(Location, string)>()); + Assert.Empty(result.Diagnostics); // With STJ usage. source = """ @@ -275,9 +245,7 @@ public static void Main() compilation = CompilationHelper.CreateCompilation(source); result = CompilationHelper.RunJsonSourceGenerator(compilation); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, result.Diagnostics, Array.Empty<(Location, string)>()); + Assert.Empty(result.Diagnostics); } [Fact] @@ -286,9 +254,7 @@ public void DoNotWarnOnClassesWithInitOnlyProperties() Compilation compilation = CompilationHelper.CreateCompilationWithInitOnlyProperties(); JsonSourceGeneratorResult result = CompilationHelper.RunJsonSourceGenerator(compilation); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, result.Diagnostics, Array.Empty<(Location, string)>()); + Assert.Empty(result.Diagnostics); } [Fact] @@ -297,9 +263,7 @@ public void DoNotWarnOnClassesWithConstructorInitOnlyProperties() Compilation compilation = CompilationHelper.CreateCompilationWithConstructorInitOnlyProperties(); JsonSourceGeneratorResult result = CompilationHelper.RunJsonSourceGenerator(compilation); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, result.Diagnostics, Array.Empty<(Location, string)>()); + Assert.Empty(result.Diagnostics); } [Fact] @@ -308,9 +272,7 @@ public void DoNotWarnOnClassesWithMixedInitOnlyProperties() Compilation compilation = CompilationHelper.CreateCompilationWithMixedInitOnlyProperties(); JsonSourceGeneratorResult result = CompilationHelper.RunJsonSourceGenerator(compilation); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, result.Diagnostics, Array.Empty<(Location, string)>()); + Assert.Empty(result.Diagnostics); } [Fact] @@ -319,9 +281,7 @@ public void DoNotWarnOnRecordsWithInitOnlyPositionalParameters() Compilation compilation = CompilationHelper.CreateCompilationWithRecordPositionalParameters(); JsonSourceGeneratorResult result = CompilationHelper.RunJsonSourceGenerator(compilation); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, result.Diagnostics, Array.Empty<(Location, string)>()); + Assert.Empty(result.Diagnostics); } [Fact] @@ -330,9 +290,7 @@ public void DoNotWarnOnClassesWithRequiredProperties() Compilation compilation = CompilationHelper.CreateCompilationWithRequiredProperties(); JsonSourceGeneratorResult result = CompilationHelper.RunJsonSourceGenerator(compilation); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, result.Diagnostics, Array.Empty<(Location, string)>()); + Assert.Empty(result.Diagnostics); } [Fact] @@ -344,17 +302,19 @@ public void WarnOnClassesWithInaccessibleJsonIncludeProperties() Location idLocation = compilation.GetSymbolsWithName("Id").First().Locations[0]; Location address2Location = compilation.GetSymbolsWithName("Address2").First().Locations[0]; Location countryLocation = compilation.GetSymbolsWithName("Country").First().Locations[0]; + Location internalFieldLocation = compilation.GetSymbolsWithName("internalField").First().Locations[0]; + Location privateFieldLocation = compilation.GetSymbolsWithName("privateField").First().Locations[0]; - (Location, string)[] expectedWarningDiagnostics = new (Location, string)[] + var expectedDiagnostics = new DiagnosticData[] { - (idLocation, "The member 'Location.Id' has been annotated with the JsonIncludeAttribute but is not visible to the source generator."), - (address2Location, "The member 'Location.Address2' has been annotated with the JsonIncludeAttribute but is not visible to the source generator."), - (countryLocation, "The member 'Location.Country' has been annotated with the JsonIncludeAttribute but is not visible to the source generator.") + new(DiagnosticSeverity.Warning, idLocation, "The member 'Location.Id' has been annotated with the JsonIncludeAttribute but is not visible to the source generator."), + new(DiagnosticSeverity.Warning, address2Location, "The member 'Location.Address2' has been annotated with the JsonIncludeAttribute but is not visible to the source generator."), + new(DiagnosticSeverity.Warning, countryLocation, "The member 'Location.Country' has been annotated with the JsonIncludeAttribute but is not visible to the source generator."), + new(DiagnosticSeverity.Warning, internalFieldLocation, "The member 'Location.internalField' has been annotated with the JsonIncludeAttribute but is not visible to the source generator."), + new(DiagnosticSeverity.Warning, privateFieldLocation, "The member 'Location.privateField' has been annotated with the JsonIncludeAttribute but is not visible to the source generator."), }; - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, result.Diagnostics, expectedWarningDiagnostics, sort: false); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, result.Diagnostics, Array.Empty<(Location, string)>()); + CompilationHelper.AssertEqualDiagnosticMessages(expectedDiagnostics, result.Diagnostics); } [Fact] @@ -365,14 +325,30 @@ public void PolymorphicClassWarnsOnFastPath() Location myBaseClassLocation = compilation.GetSymbolsWithName("MyBaseClass").First().Locations[0]; - (Location, string)[] expectedWarningDiagnostics = new (Location, string)[] + var expectedDiagnostics = new DiagnosticData[] + { + new(DiagnosticSeverity.Warning, myBaseClassLocation, "Type 'HelloWorld.MyBaseClass' is annotated with 'JsonDerivedTypeAttribute' which is not supported in 'JsonSourceGenerationMode.Serialization'."), + }; + + CompilationHelper.AssertEqualDiagnosticMessages(expectedDiagnostics, result.Diagnostics); + } + + [Fact] + public void JsonStringEnumConverterWarns() + { + Compilation compilation = CompilationHelper.CreateTypesAnnotatedWithJsonStringEnumConverter(); + JsonSourceGeneratorResult result = CompilationHelper.RunJsonSourceGenerator(compilation); + + Location enum2PropLocation = compilation.GetSymbolsWithName("Enum2Prop").First().Locations[0]; + Location enum1TypeLocation = compilation.GetSymbolsWithName("Enum1").First().Locations[0]; + + var expectedDiagnostics = new DiagnosticData[] { - (myBaseClassLocation, "Type 'HelloWorld.MyBaseClass' is annotated with 'JsonDerivedTypeAttribute' which is not supported in 'JsonSourceGenerationMode.Serialization'."), + new(DiagnosticSeverity.Warning, enum1TypeLocation, "The member 'HelloWorld.Enum1' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter' instead."), + new(DiagnosticSeverity.Warning, enum2PropLocation, "The member 'HelloWorld.MyClass.Enum2Prop' has been annotated with 'JsonStringEnumConverter' which is not supported in native AOT. Consider using the generic 'JsonStringEnumConverter' instead."), }; - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, result.Diagnostics, expectedWarningDiagnostics, sort: false); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, result.Diagnostics, Array.Empty<(Location, string)>()); + CompilationHelper.AssertEqualDiagnosticMessages(expectedDiagnostics, result.Diagnostics); } } } 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 a0e038aa1062eb..e511ca4ba6c79e 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 @@ -230,9 +230,7 @@ public JsonSerializableAttribute(Type type) { } Assert.Empty(result.AllGeneratedTypes); } - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, result.Diagnostics, Array.Empty<(Location, string)>()); + Assert.Empty(result.Diagnostics); } [Theory] @@ -262,10 +260,7 @@ public JsonSerializableAttribute(string typeInfoPropertyName, Type type) { } JsonSourceGeneratorResult result = CompilationHelper.RunJsonSourceGenerator(compilation); Assert.Empty(result.AllGeneratedTypes); - - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, result.Diagnostics, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, result.Diagnostics, Array.Empty<(Location, string)>()); + Assert.Empty(result.Diagnostics); } [Fact] @@ -426,8 +421,10 @@ public record AppRecord(int Id) CheckCompilationDiagnosticsErrors(result.Diagnostics); CheckCompilationDiagnosticsErrors(result.NewCompilation.GetDiagnostics()); - Assert.Equal(4, result.AllGeneratedTypes.Count()); + Assert.Equal(3, result.AllGeneratedTypes.Count()); result.AssertContainsType("global::HelloWorld.AppRecord"); + result.AssertContainsType("string"); + result.AssertContainsType("int"); } [Fact] @@ -463,8 +460,10 @@ internal partial class JsonContext : JsonSerializerContext CheckCompilationDiagnosticsErrors(result.Diagnostics); CheckCompilationDiagnosticsErrors(result.NewCompilation.GetDiagnostics()); - Assert.Equal(4, result.AllGeneratedTypes.Count()); + Assert.Equal(3, result.AllGeneratedTypes.Count()); result.AssertContainsType("global::ReferencedAssembly.LibRecord"); + result.AssertContainsType("string"); + result.AssertContainsType("int"); } [Fact] @@ -504,8 +503,10 @@ internal record AppRecord : LibRecord CheckCompilationDiagnosticsErrors(result.Diagnostics); CheckCompilationDiagnosticsErrors(result.NewCompilation.GetDiagnostics()); - Assert.Equal(4, result.AllGeneratedTypes.Count()); + Assert.Equal(3, result.AllGeneratedTypes.Count()); result.AssertContainsType("global::HelloWorld.AppRecord"); + result.AssertContainsType("string"); + result.AssertContainsType("int"); } private void CheckCompilationDiagnosticsErrors(ImmutableArray diagnostics) @@ -596,9 +597,7 @@ public class ClassWithObsolete ImmutableArray generatorDiags = result.NewCompilation.GetDiagnostics(); // No diagnostics expected. - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, generatorDiags, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, generatorDiags, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, generatorDiags, Array.Empty<(Location, string)>()); + Assert.Empty(result.Diagnostics); } [Fact] @@ -626,9 +625,7 @@ public class ClassWithPropertiesAndFieldsThatAreReservedKeywords ImmutableArray generatorDiags = result.NewCompilation.GetDiagnostics(); // No diagnostics expected. - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, generatorDiags, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, generatorDiags, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, generatorDiags, Array.Empty<(Location, string)>()); + Assert.Empty(result.Diagnostics); } [Fact] @@ -689,9 +686,66 @@ public class ClassWithPropertyNameThatIsAReservedKeyword ImmutableArray generatorDiags = result.NewCompilation.GetDiagnostics(); // No diagnostics expected. - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Info, generatorDiags, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Warning, generatorDiags, Array.Empty<(Location, string)>()); - CompilationHelper.CheckDiagnosticMessages(DiagnosticSeverity.Error, generatorDiags, Array.Empty<(Location, string)>()); + Assert.Empty(result.Diagnostics); + } + + [Fact] + public void UseUnderlyingTypeConverterForNullableType() + { + // Compile the referenced assembly first. + Compilation referencedCompilation = CompilationHelper.CreateReferencedLocationCompilation(); + + // Emit the image of the referenced assembly. + byte[] referencedImage = CompilationHelper.CreateAssemblyImage(referencedCompilation); + + string source = """ + using ReferencedAssembly; + using System; + using System.Text.Json; + using System.Text.Json.Serialization; + namespace Test + { + [JsonSourceGenerationOptions] + [JsonSerializable(typeof(Sample))] + public partial class SourceGenerationContext : JsonSerializerContext + { + } + public class Sample + { + [JsonConverter(typeof(DateTimeOffsetToTimestampJsonConverter))] + public DateTimeOffset Start { get; set; } + [JsonConverter(typeof(DateTimeOffsetToTimestampJsonConverter))] + public DateTimeOffset? End { get; set; } // Without this property, this is fine + } + public class DateTimeOffsetToTimestampJsonConverter : JsonConverter + { + internal const long TicksPerMicroseconds = 10; + public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var value = reader.GetInt64(); + return new DateTimeOffset(value * TicksPerMicroseconds, TimeSpan.Zero); + } + public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options) + { + writer.WriteNumberValue(value.Ticks / TicksPerMicroseconds); + } + } + } + """; + + MetadataReference[] additionalReferences = { MetadataReference.CreateFromImage(referencedImage) }; + + Compilation compilation = CompilationHelper.CreateCompilation(source, additionalReferences); + + JsonSourceGeneratorResult result = CompilationHelper.RunJsonSourceGenerator(compilation); + + // Make sure compilation was successful. + CheckCompilationDiagnosticsErrors(result.NewCompilation.GetDiagnostics()); + + Assert.Equal(3, result.AllGeneratedTypes.Count()); + result.AssertContainsType("global::Test.Sample"); + result.AssertContainsType("global::System.DateTimeOffset"); + result.AssertContainsType("global::System.DateTimeOffset?"); } [Fact] diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.BadConverters.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.BadConverters.cs index 062a7e9335896d..adceb7d3cddb25 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.BadConverters.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/CustomConverterTests/CustomConverterTests.BadConverters.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; +using System.Reflection; using Xunit; namespace System.Text.Json.Serialization.Tests @@ -113,44 +114,60 @@ private class InvalidTypeConverterClass public ICollection MyEnumValues { get; set; } } + private class InvalidEnumTypeConverterClass + { + [JsonConverter(typeof(JsonStringEnumConverter))] + public InvalidTypeConverterEnum MyEnumValues { get; set; } + } + private enum InvalidTypeConverterEnum { Value1, Value2, } - [Fact] - public static void AttributeOnPropertyFail() + [Theory] + [InlineData(typeof(InvalidTypeConverterClass), + "System.Text.Json.Serialization.Tests.CustomConverterTests+InvalidTypeConverterClass.MyEnumValues", + "System.Collections.Generic.ICollection`1[System.Text.Json.Serialization.Tests.CustomConverterTests+InvalidTypeConverterEnum]")] + [InlineData(typeof(InvalidEnumTypeConverterClass), + "System.Text.Json.Serialization.Tests.CustomConverterTests+InvalidEnumTypeConverterClass.MyEnumValues", + "System.Text.Json.Serialization.Tests.CustomConverterTests+InvalidTypeConverterEnum")] + public static void AttributeOnPropertyFail(Type type, string propertyName, string propertyTypeName) { + object value = Activator.CreateInstance(type); InvalidOperationException ex; - ex = Assert.Throws(() => JsonSerializer.Serialize(new InvalidTypeConverterClass())); + ex = Assert.Throws(() => JsonSerializer.Serialize(value, type)); // Message should be in the form "The converter specified on 'System.Text.Json.Serialization.Tests.CustomConverterTests+InvalidTypeConverterClass.MyEnumValues' is not compatible with the type 'System.Collections.Generic.ICollection`1[System.Text.Json.Serialization.Tests.CustomConverterTests+InvalidTypeConverterEnum]'." - Assert.Contains("'System.Text.Json.Serialization.Tests.CustomConverterTests+InvalidTypeConverterClass.MyEnumValues'", ex.Message); + Assert.Contains($"'{propertyName}'", ex.Message); - ex = Assert.Throws(() => JsonSerializer.Deserialize("{}")); - Assert.Contains("'System.Text.Json.Serialization.Tests.CustomConverterTests+InvalidTypeConverterClass.MyEnumValues'", ex.Message); - Assert.Contains("'System.Collections.Generic.ICollection`1[System.Text.Json.Serialization.Tests.CustomConverterTests+InvalidTypeConverterEnum]'", ex.Message); + ex = Assert.Throws(() => JsonSerializer.Deserialize("{}", type)); + Assert.Contains($"'{propertyName}'", ex.Message); + Assert.Contains($"'{propertyTypeName}'", ex.Message); } [JsonConverter(typeof(JsonStringEnumConverter))] private class InvalidTypeConverterClassWithAttribute { } - [Fact] - public static void AttributeOnClassFail() - { - const string expectedSubStr = "'System.Text.Json.Serialization.Tests.CustomConverterTests+InvalidTypeConverterClassWithAttribute'"; + [JsonConverter(typeof(JsonStringEnumConverter))] + private enum InvalidTypeConverterEnumWithAttribute { } + [Theory] + [InlineData(typeof(InvalidTypeConverterClassWithAttribute), "System.Text.Json.Serialization.Tests.CustomConverterTests+InvalidTypeConverterClassWithAttribute")] + [InlineData(typeof(InvalidTypeConverterEnumWithAttribute), "System.Text.Json.Serialization.Tests.CustomConverterTests+InvalidTypeConverterEnumWithAttribute")] + public static void AttributeOnClassFail(Type type, string expectedSubStr) + { InvalidOperationException ex; + object value = Activator.CreateInstance(type); - ex = Assert.Throws(() => JsonSerializer.Serialize(new InvalidTypeConverterClassWithAttribute())); - // Message should be in the form "The converter specified on 'System.Text.Json.Serialization.Tests.CustomConverterTests+InvalidTypeConverterClassWithAttribute' is not compatible with the type 'System.Text.Json.Serialization.Tests.CustomConverterTests+InvalidTypeConverterClassWithAttribute'." + ex = Assert.Throws(() => JsonSerializer.Serialize(value, type)); int pos = ex.Message.IndexOf(expectedSubStr); Assert.True(pos > 0); Assert.Contains(expectedSubStr, ex.Message.Substring(pos + expectedSubStr.Length)); // The same string is repeated again. - ex = Assert.Throws(() => JsonSerializer.Deserialize("{}")); + ex = Assert.Throws(() => JsonSerializer.Deserialize("{}", type)); pos = ex.Message.IndexOf(expectedSubStr); Assert.True(pos > 0); Assert.Contains(expectedSubStr, ex.Message.Substring(pos + expectedSubStr.Length)); diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/EnumConverterTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/EnumConverterTests.cs index ddf0e5fa7cc4ea..2c7516ff0009f3 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/EnumConverterTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/Serialization/EnumConverterTests.cs @@ -13,11 +13,49 @@ namespace System.Text.Json.Serialization.Tests { public class EnumConverterTests { - [Fact] - public void ConvertDayOfWeek() + [Theory] + [InlineData(typeof(JsonStringEnumConverter), typeof(DayOfWeek))] + [InlineData(typeof(JsonStringEnumConverter), typeof(MyCustomEnum))] + [InlineData(typeof(JsonStringEnumConverter), typeof(DayOfWeek))] + [InlineData(typeof(JsonStringEnumConverter), typeof(MyCustomEnum))] + public static void JsonStringEnumConverter_SupportedType_WorksAsExpected(Type converterType, Type supportedType) + { + var options = new JsonSerializerOptions(); + var factory = (JsonConverterFactory)Activator.CreateInstance(converterType); + + Assert.True(factory.CanConvert(supportedType)); + + JsonConverter converter = factory.CreateConverter(supportedType, options); + // TODO use https://github.com/dotnet/runtime/issues/63898 once implemented + Type expectedConverterType = typeof(JsonConverter<>).MakeGenericType(supportedType); + Assert.IsAssignableFrom(expectedConverterType, converter); + } + + [Theory] + [InlineData(typeof(JsonStringEnumConverter), typeof(int))] + [InlineData(typeof(JsonStringEnumConverter), typeof(string))] + [InlineData(typeof(JsonStringEnumConverter), typeof(JsonStringEnumConverter))] + [InlineData(typeof(JsonStringEnumConverter), typeof(int))] + [InlineData(typeof(JsonStringEnumConverter), typeof(string))] + [InlineData(typeof(JsonStringEnumConverter), typeof(JsonStringEnumConverter))] + [InlineData(typeof(JsonStringEnumConverter), typeof(MyCustomEnum))] + [InlineData(typeof(JsonStringEnumConverter), typeof(DayOfWeek))] + public static void JsonStringEnumConverter_InvalidType_ThrowsArgumentOutOfRangeException(Type converterType, Type unsupportedType) + { + var options = new JsonSerializerOptions(); + var factory = (JsonConverterFactory)Activator.CreateInstance(converterType); + + Assert.False(factory.CanConvert(unsupportedType)); + ArgumentOutOfRangeException ex = Assert.Throws(() => factory.CreateConverter(unsupportedType, options)); + Assert.Contains(unsupportedType.FullName, ex.Message); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void ConvertDayOfWeek(bool useGenericVariant) { - JsonSerializerOptions options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter()); + JsonSerializerOptions options = CreateStringEnumOptionsForType(useGenericVariant); WhenClass when = JsonSerializer.Deserialize(@"{""Day"":""Monday""}", options); Assert.Equal(DayOfWeek.Monday, when.Day); @@ -36,8 +74,7 @@ public void ConvertDayOfWeek() Assert.Equal(@"""Friday""", json); // Try a unique naming policy - options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter(new ToLowerNamingPolicy())); + options = CreateStringEnumOptionsForType(useGenericVariant, new ToLowerNamingPolicy()); json = JsonSerializer.Serialize(DayOfWeek.Friday, options); Assert.Equal(@"""friday""", json); @@ -47,8 +84,7 @@ public void ConvertDayOfWeek() Assert.Equal(@"-1", json); // Not permitting integers should throw - options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter(allowIntegerValues: false)); + options = CreateStringEnumOptionsForType(useGenericVariant, allowIntegerValues: false); Assert.Throws(() => JsonSerializer.Serialize((DayOfWeek)(-1), options)); } @@ -62,11 +98,12 @@ public class WhenClass public DayOfWeek Day { get; set; } } - [Fact] - public void ConvertFileAttributes() + [Theory] + [InlineData(false)] + [InlineData(true)] + public void ConvertFileAttributes(bool useGenericVariant) { - JsonSerializerOptions options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter()); + JsonSerializerOptions options = CreateStringEnumOptionsForType(useGenericVariant); FileState state = JsonSerializer.Deserialize(@"{""Attributes"":""ReadOnly""}", options); Assert.Equal(FileAttributes.ReadOnly, state.Attributes); @@ -95,8 +132,7 @@ public void ConvertFileAttributes() Assert.Equal(@"""Temporary, Offline""", json); // Try a unique casing - options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter(new ToLowerNamingPolicy())); + options = CreateStringEnumOptionsForType(useGenericVariant, new ToLowerNamingPolicy()); json = JsonSerializer.Serialize(FileAttributes.NoScrubData, options); Assert.Equal(@"""noscrubdata""", json); @@ -108,13 +144,11 @@ public void ConvertFileAttributes() Assert.Equal(@"-1", json); // Not permitting integers should throw - options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter(allowIntegerValues: false)); + options = CreateStringEnumOptionsForType(useGenericVariant, allowIntegerValues: false); Assert.Throws(() => JsonSerializer.Serialize((FileAttributes)(-1), options)); // Flag values honor naming policy correctly - options = new JsonSerializerOptions(); - options.Converters.Add(new JsonStringEnumConverter(new SimpleSnakeCasePolicy())); + options = CreateStringEnumOptionsForType(useGenericVariant, new SimpleSnakeCasePolicy()); json = JsonSerializer.Serialize( FileAttributes.Directory | FileAttributes.Compressed | FileAttributes.IntegrityStream, @@ -140,6 +174,11 @@ public class Week public DayOfWeek WorkEnd { get; set; } [JsonConverter(typeof(LowerCaseEnumConverter))] public DayOfWeek WeekEnd { get; set; } + + [JsonConverter(typeof(JsonStringEnumConverter))] + public DayOfWeek WorkStart2 { get; set; } + [JsonConverter(typeof(LowerCaseEnumConverter))] + public DayOfWeek WeekEnd2 { get; set; } } private class LowerCaseEnumConverter : JsonStringEnumConverter @@ -149,17 +188,34 @@ public LowerCaseEnumConverter() : base(new ToLowerNamingPolicy()) } } + private class LowerCaseEnumConverter : JsonStringEnumConverter + where TEnum : struct, Enum + { + public LowerCaseEnumConverter() : base(new ToLowerNamingPolicy()) + { + } + } + [Fact] public void ConvertEnumUsingAttributes() { - Week week = new Week { WorkStart = DayOfWeek.Monday, WorkEnd = DayOfWeek.Friday, WeekEnd = DayOfWeek.Saturday }; + Week week = new Week { + WorkStart = DayOfWeek.Monday, + WorkEnd = DayOfWeek.Friday, + WeekEnd = DayOfWeek.Saturday, + WorkStart2 = DayOfWeek.Tuesday, + WeekEnd2 = DayOfWeek.Thursday, + }; + string json = JsonSerializer.Serialize(week); - Assert.Equal(@"{""WorkStart"":""Monday"",""WorkEnd"":5,""WeekEnd"":""saturday""}", json); + Assert.Equal("""{"WorkStart":"Monday","WorkEnd":5,"WeekEnd":"saturday","WorkStart2":"Tuesday","WeekEnd2":"thursday"}""", json); week = JsonSerializer.Deserialize(json); Assert.Equal(DayOfWeek.Monday, week.WorkStart); Assert.Equal(DayOfWeek.Friday, week.WorkEnd); Assert.Equal(DayOfWeek.Saturday, week.WeekEnd); + Assert.Equal(DayOfWeek.Tuesday, week.WorkStart2); + Assert.Equal(DayOfWeek.Thursday, week.WeekEnd2); } [Fact] @@ -190,26 +246,34 @@ private enum MyCustomEnum Second = 2 } - [Fact] - public void EnumWithConverterAttribute() + [JsonConverter(typeof(JsonStringEnumConverter))] + private enum MyCustomEnum2 { - string json = JsonSerializer.Serialize(MyCustomEnum.Second); - Assert.Equal(@"""Second""", json); + First = 1, + Second = 2 + } - MyCustomEnum obj = JsonSerializer.Deserialize("\"Second\""); - Assert.Equal(MyCustomEnum.Second, obj); + [Theory] + [InlineData(typeof(MyCustomEnum), MyCustomEnum.Second, "\"Second\"", "2")] + [InlineData(typeof(MyCustomEnum2), MyCustomEnum2.Second, "\"Second\"", "2")] + public void EnumWithConverterAttribute(Type enumType, object value, string expectedJson, string alternativeJson) + { + string json = JsonSerializer.Serialize(value, enumType); + Assert.Equal(expectedJson, json); + + object? result = JsonSerializer.Deserialize(json, enumType); + Assert.Equal(value, result); - obj = JsonSerializer.Deserialize("2"); - Assert.Equal(MyCustomEnum.Second, obj); + result = JsonSerializer.Deserialize(alternativeJson, enumType); + Assert.Equal(value, result); } - [Fact] - public static void EnumWithNoValues() + [Theory] + [InlineData(false)] + [InlineData(true)] + public static void EnumWithNoValues(bool useGenericVariant) { - var options = new JsonSerializerOptions - { - Converters = { new JsonStringEnumConverter() } - }; + JsonSerializerOptions options = CreateStringEnumOptionsForType(useGenericVariant); Assert.Equal("-1", JsonSerializer.Serialize((EmptyEnum)(-1), options)); Assert.Equal("1", JsonSerializer.Serialize((EmptyEnum)(1), options)); @@ -217,13 +281,12 @@ public static void EnumWithNoValues() public enum EmptyEnum { }; - [Fact] - public static void MoreThan64EnumValuesToSerialize() + [Theory] + [InlineData(false)] + [InlineData(true)] + public static void MoreThan64EnumValuesToSerialize(bool useGenericVariant) { - var options = new JsonSerializerOptions - { - Converters = { new JsonStringEnumConverter() } - }; + JsonSerializerOptions options = CreateStringEnumOptionsForType(useGenericVariant); for (int i = 0; i < 128; i++) { @@ -234,13 +297,12 @@ public static void MoreThan64EnumValuesToSerialize() } } - [Fact] - public static void MoreThan64EnumValuesToSerializeWithNamingPolicy() + [Theory] + [InlineData(false)] + [InlineData(true)] + public static void MoreThan64EnumValuesToSerializeWithNamingPolicy(bool useGenericVariant) { - var options = new JsonSerializerOptions - { - Converters = { new JsonStringEnumConverter(new ToLowerNamingPolicy()) } - }; + JsonSerializerOptions options = CreateStringEnumOptionsForType(useGenericVariant, new ToLowerNamingPolicy()); for (int i = 0; i < 128; i++) { @@ -556,16 +618,12 @@ public enum SampleEnumSByte : sbyte G = 1 << 6, } - [Fact] - public static void Honor_EnumNamingPolicy_On_Deserialization() + [Theory] + [InlineData(false)] + [InlineData(true)] + public static void Honor_EnumNamingPolicy_On_Deserialization(bool useGenericVariant) { - JsonSerializerOptions options = new() - { - Converters = - { - new JsonStringEnumConverter(namingPolicy: new SimpleSnakeCasePolicy() ) - } - }; + JsonSerializerOptions options = CreateStringEnumOptionsForType(useGenericVariant, new SimpleSnakeCasePolicy()); BindingFlags bindingFlags = JsonSerializer.Deserialize(@"""non_public""", options); Assert.Equal(BindingFlags.NonPublic, bindingFlags); @@ -585,18 +643,14 @@ public static void Honor_EnumNamingPolicy_On_Deserialization() Assert.Null(JsonSerializer.Deserialize("null", options)); } - [Fact] - public static void EnumDictionaryKeyDeserialization() + [Theory] + [InlineData(false)] + [InlineData(true)] + public static void EnumDictionaryKeyDeserialization(bool useGenericVariant) { JsonNamingPolicy snakeCasePolicy = new SimpleSnakeCasePolicy(); - JsonSerializerOptions options = new() - { - Converters = - { - new JsonStringEnumConverter(namingPolicy: snakeCasePolicy) - }, - DictionaryKeyPolicy = snakeCasePolicy - }; + JsonSerializerOptions options = CreateStringEnumOptionsForType(useGenericVariant); + options.DictionaryKeyPolicy = snakeCasePolicy; // Baseline. var dict = JsonSerializer.Deserialize>(@"{""NonPublic, Public"": 1}", options); @@ -635,5 +689,18 @@ private class ZeroAppenderPolicy : JsonNamingPolicy { public override string ConvertName(string name) => name + "0"; } + + private static JsonSerializerOptions CreateStringEnumOptionsForType(bool useGenericVariant, JsonNamingPolicy? namingPolicy = null, bool allowIntegerValues = true) where TEnum : struct, Enum + { + return new JsonSerializerOptions + { + Converters = + { + useGenericVariant + ? new JsonStringEnumConverter(namingPolicy, allowIntegerValues) + : new JsonStringEnumConverter(namingPolicy, allowIntegerValues) + } + }; + } } } 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 88e371435571f2..91ca5c015a64df 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 @@ -157,11 +157,16 @@ public static IEnumerable PointerTypes() // and typeof(int*) can't be a generic parameter to the generic overload. public static IEnumerable TypesWithInvalidMembers_WithMembers() { - yield return new object[] { typeof(Memory), typeof(Span), "Span" }; // Contains Span property. + yield return new object[] { typeof(ClassWithSpan), typeof(Span), "Span" }; yield return new object[] { typeof(ClassWithIntPtr), s_intPtrType, "IntPtr" }; } + private class ClassWithSpan + { + public Span Span => Array.Empty(); + } + private class ClassWithIntPtr { public unsafe int* IntPtr { get; } 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 0c04e848d770f6..8f578a976d16ea 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 @@ -158,5 +158,21 @@ private static IList GetAndValidateCombinedResolvers(IJso return list; } + + [Fact] + public static void NullResolver_ReturnsObjectMetadata() + { + var options = new JsonSerializerOptions(); + var resolver = new NullResolver(); + Assert.Null(resolver.GetTypeInfo(typeof(object), options)); + + options.TypeInfoResolver = resolver; + Assert.IsAssignableFrom>(options.GetTypeInfo(typeof(object))); + } + + public sealed class NullResolver : IJsonTypeInfoResolver + { + public JsonTypeInfo? GetTypeInfo(Type type, JsonSerializerOptions options) => null; + } } } 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 4a454f932b3262..575cd0eaf028ae 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 @@ -464,7 +464,7 @@ public static void JsonEncodedTextStringsCustomAllowAll(string message, string e [Fact] public static void Options_GetConverterForObjectJsonElement_GivesCorrectConverter() { - GenericObjectOrJsonElementConverterTestHelper("ObjectConverter", new object(), "{}"); + GenericObjectOrJsonElementConverterTestHelper("DefaultObjectConverter", new object(), "{}"); JsonElement element = JsonDocument.Parse("[3]").RootElement; GenericObjectOrJsonElementConverterTestHelper("JsonElementConverter", element, "[3]"); } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.GetJsonTypeInfo.g.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.GetJsonTypeInfo.g.cs index 61eec78d7932d1..5d78355f68bb0d 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.GetJsonTypeInfo.g.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.GetJsonTypeInfo.g.cs @@ -27,6 +27,11 @@ public partial class Net60GeneratedContext return this.ClassWithCustomConverter; } + if (type == typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net60.MyLinkedList)) + { + return this.MyLinkedList; + } + return null!; } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.ListDateTimeOffset.g.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.ListDateTimeOffset.g.cs index f969da8b4c88cf..576f4f054ca40c 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.ListDateTimeOffset.g.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.ListDateTimeOffset.g.cs @@ -1,4 +1,11 @@ -// +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Source files represent a source generated JsonSerializerContext as produced by the .NET 6 SDK. +// Used to validate correctness of contexts generated by previous SDKs against the current System.Text.Json runtime components. +// Unless absolutely necessary DO NOT MODIFY any of these files -- it would invalidate the purpose of the regression tests. + +// #nullable enable // Suppress warnings about [Obsolete] member usage in generated code. diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.MyLinkedList.g.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.MyLinkedList.g.cs new file mode 100644 index 00000000000000..fecbc6b0735501 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.MyLinkedList.g.cs @@ -0,0 +1,144 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Source files represent a source generated JsonSerializerContext as produced by the .NET 6 SDK. +// Used to validate correctness of contexts generated by previous SDKs against the current System.Text.Json runtime components. +// Unless absolutely necessary DO NOT MODIFY any of these files -- it would invalidate the purpose of the regression tests. + +// +#nullable enable + +// Suppress warnings about [Obsolete] member usage in generated code. +#pragma warning disable CS0618 + +namespace System.Text.Json.Tests.SourceGenRegressionTests.Net60 +{ + public partial class Net60GeneratedContext + { + private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo? _MyLinkedList; + public global::System.Text.Json.Serialization.Metadata.JsonTypeInfo MyLinkedList + { + get + { + if (_MyLinkedList == null) + { + global::System.Text.Json.Serialization.JsonConverter? customConverter; + if (Options.Converters.Count > 0 && (customConverter = GetRuntimeProvidedCustomConverter(typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net60.MyLinkedList))) != null) + { + _MyLinkedList = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo(Options, customConverter); + } + else + { + global::System.Text.Json.Serialization.Metadata.JsonObjectInfoValues objectInfo = new global::System.Text.Json.Serialization.Metadata.JsonObjectInfoValues() + { + ObjectCreator = null, + ObjectWithParameterizedConstructorCreator = static (args) => new global::System.Text.Json.Tests.SourceGenRegressionTests.Net60.MyLinkedList((global::System.Int32)args[0], (global::System.Text.Json.Tests.SourceGenRegressionTests.Net60.MyLinkedList)args[1]), + PropertyMetadataInitializer = MyLinkedListPropInit, + ConstructorParameterMetadataInitializer = MyLinkedListCtorParamInit, + NumberHandling = default, + SerializeHandler = MyLinkedListSerializeHandler + }; + + _MyLinkedList = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateObjectInfo(Options, objectInfo); + } + } + + return _MyLinkedList; + } + } + + private static global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[] MyLinkedListPropInit(global::System.Text.Json.Serialization.JsonSerializerContext context) + { + global::System.Text.Json.Tests.SourceGenRegressionTests.Net60.Net60GeneratedContext jsonContext = (global::System.Text.Json.Tests.SourceGenRegressionTests.Net60.Net60GeneratedContext)context; + global::System.Text.Json.JsonSerializerOptions options = context.Options; + + global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[] properties = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[2]; + + global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues info0 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues() + { + IsProperty = true, + IsPublic = true, + IsVirtual = false, + DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net60.MyLinkedList), + PropertyTypeInfo = jsonContext.Int32, + Converter = null, + Getter = static (obj) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net60.MyLinkedList)obj).Value, + Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net60.MyLinkedList)obj).Value = value!, + IgnoreCondition = null, + HasJsonInclude = false, + IsExtensionData = false, + NumberHandling = default, + PropertyName = "Value", + JsonPropertyName = null + }; + + properties[0] = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo(options, info0); + + global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues info1 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues() + { + IsProperty = true, + IsPublic = true, + IsVirtual = false, + DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net60.MyLinkedList), + PropertyTypeInfo = jsonContext.MyLinkedList, + Converter = null, + Getter = static (obj) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net60.MyLinkedList)obj).Nested!, + Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net60.MyLinkedList)obj).Nested = value!, + IgnoreCondition = null, + HasJsonInclude = false, + IsExtensionData = false, + NumberHandling = default, + PropertyName = "Nested", + JsonPropertyName = null + }; + + properties[1] = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo(options, info1); + + return properties; + } + + private static void MyLinkedListSerializeHandler(global::System.Text.Json.Utf8JsonWriter writer, global::System.Text.Json.Tests.SourceGenRegressionTests.Net60.MyLinkedList? value) + { + if (value == null) + { + writer.WriteNullValue(); + return; + } + + writer.WriteStartObject(); + writer.WriteNumber(PropName_Value, value.Value); + writer.WritePropertyName(PropName_Nested); + MyLinkedListSerializeHandler(writer, value.Nested!); + + writer.WriteEndObject(); + } + + private static global::System.Text.Json.Serialization.Metadata.JsonParameterInfoValues[] MyLinkedListCtorParamInit() + { + global::System.Text.Json.Serialization.Metadata.JsonParameterInfoValues[] parameters = new global::System.Text.Json.Serialization.Metadata.JsonParameterInfoValues[2]; + global::System.Text.Json.Serialization.Metadata.JsonParameterInfoValues info; + + info = new() + { + Name = "value", + ParameterType = typeof(global::System.Int32), + Position = 0, + HasDefaultValue = false, + DefaultValue = default(global::System.Int32) + }; + parameters[0] = info; + + info = new() + { + Name = "nested", + ParameterType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net60.MyLinkedList), + Position = 1, + HasDefaultValue = false, + DefaultValue = default(global::System.Text.Json.Tests.SourceGenRegressionTests.Net60.MyLinkedList) + }; + parameters[1] = info; + + return parameters; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.PropertyNames.g.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.PropertyNames.g.cs index 84f4b425d6e7a0..21963c2a94c889 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.PropertyNames.g.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.PropertyNames.g.cs @@ -24,5 +24,7 @@ public partial class Net60GeneratedContext private static readonly global::System.Text.Json.JsonEncodedText PropName_SummaryWords = global::System.Text.Json.JsonEncodedText.Encode("SummaryWords"); private static readonly global::System.Text.Json.JsonEncodedText PropName_High = global::System.Text.Json.JsonEncodedText.Encode("High"); private static readonly global::System.Text.Json.JsonEncodedText PropName_Low = global::System.Text.Json.JsonEncodedText.Encode("Low"); + private static readonly global::System.Text.Json.JsonEncodedText PropName_Value = global::System.Text.Json.JsonEncodedText.Encode("Value"); + private static readonly global::System.Text.Json.JsonEncodedText PropName_Nested = global::System.Text.Json.JsonEncodedText.Encode("Nested"); } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.cs index 7158db21983038..207878bdbfb12c 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.cs @@ -12,6 +12,7 @@ namespace System.Text.Json.Tests.SourceGenRegressionTests.Net60 { //[JsonSerializable(typeof(WeatherForecastWithPOCOs))] //[JsonSerializable(typeof(ClassWithCustomConverter))] + //[JsonSerializable(typeof(MyLinkedList))] public partial class Net60GeneratedContext : JsonSerializerContext { } public class WeatherForecastWithPOCOs @@ -31,6 +32,18 @@ public class HighLowTemps public int Low { get; set; } } + public class MyLinkedList + { + public MyLinkedList(int value, MyLinkedList? nested) + { + Value = value; + Nested = nested; + } + + public int Value { get; set; } + public MyLinkedList? Nested { get; set; } + } + [JsonConverter(typeof(CustomConverter))] public class ClassWithCustomConverter { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.g.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.g.cs index 6b6bf15a8e5449..caf7ac47446795 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.g.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60/Net60GeneratedContext.g.cs @@ -14,7 +14,7 @@ namespace System.Text.Json.Tests.SourceGenRegressionTests.Net60 { - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Text.Json.SourceGeneration", "6.0.6.21309")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Text.Json.SourceGeneration", "6.0.8.17311")] public partial class Net60GeneratedContext { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60RegressionTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60RegressionTests.cs index 21a87bbb113ccc..3dba6f8d0d376b 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60RegressionTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net60RegressionTests.cs @@ -140,6 +140,26 @@ public static void HighLowTemps_ContextReportsCorrectMetadata() Assert.Equal(2, jsonPropertyInfo.Get(instance)); } + [Fact] + public static void SupportsRecursiveTypeSerialization() + { + JsonTypeInfo jsonTypeInfo = Net60GeneratedContext.Default.MyLinkedList; + + MyLinkedList linkedList = new( + value: 0, + nested: new( + value: 1, + nested: new( + value: 2, + nested: null))); + + string json = JsonSerializer.Serialize(linkedList, jsonTypeInfo); + Assert.Equal("""{"Value":0,"Nested":{"Value":1,"Nested":{"Value":2,"Nested":null}}}""", json); + + linkedList = JsonSerializer.Deserialize(json, jsonTypeInfo); + Assert.Equal(2, linkedList.Nested.Nested.Value); + } + [Fact] public static void CombinedContexts_ThrowsInvalidOperationException() { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70/Net70GeneratedContext.GetJsonTypeInfo.g.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70/Net70GeneratedContext.GetJsonTypeInfo.g.cs index 1d59adb8af1c1f..ccb1c8002ea006 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70/Net70GeneratedContext.GetJsonTypeInfo.g.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70/Net70GeneratedContext.GetJsonTypeInfo.g.cs @@ -65,6 +65,11 @@ public partial class Net70GeneratedContext: global::System.Text.Json.Serializati return this.ClassWithCustomConverter; } + if (type == typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.MyLinkedList)) + { + return this.MyLinkedList; + } + return null!; } @@ -115,6 +120,11 @@ public partial class Net70GeneratedContext: global::System.Text.Json.Serializati return Create_ClassWithCustomConverter(options, makeReadOnly: false); } + if (type == typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.MyLinkedList)) + { + return Create_MyLinkedList(options, makeReadOnly: false); + } + return null; } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70/Net70GeneratedContext.MyLinkedList.g.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70/Net70GeneratedContext.MyLinkedList.g.cs new file mode 100644 index 00000000000000..78c6e81f1ceae0 --- /dev/null +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70/Net70GeneratedContext.MyLinkedList.g.cs @@ -0,0 +1,153 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +// Source files represent a source generated JsonSerializerContext as produced by the .NET 7 SDK. +// Used to validate correctness of contexts generated by previous SDKs against the current System.Text.Json runtime components. +// Unless absolutely necessary DO NOT MODIFY any of these files -- it would invalidate the purpose of the regression tests. + +// + +#nullable enable annotations +#nullable disable warnings + +// Suppress warnings about [Obsolete] member usage in generated code. +#pragma warning disable CS0618 + +namespace System.Text.Json.Tests.SourceGenRegressionTests.Net70 +{ + public partial class Net70GeneratedContext + { + private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo? _MyLinkedList; + /// + /// Defines the source generated JSON serialization contract metadata for a given type. + /// + public global::System.Text.Json.Serialization.Metadata.JsonTypeInfo MyLinkedList + { + get => _MyLinkedList ??= Create_MyLinkedList(Options, makeReadOnly: true); + } + + private global::System.Text.Json.Serialization.Metadata.JsonTypeInfo Create_MyLinkedList(global::System.Text.Json.JsonSerializerOptions options, bool makeReadOnly) + { + global::System.Text.Json.Serialization.Metadata.JsonTypeInfo? jsonTypeInfo = null; + global::System.Text.Json.Serialization.JsonConverter? customConverter; + if (options.Converters.Count > 0 && (customConverter = GetRuntimeProvidedCustomConverter(options, typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.MyLinkedList))) != null) + { + jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateValueInfo(options, customConverter); + } + else + { + global::System.Text.Json.Serialization.Metadata.JsonObjectInfoValues objectInfo = new global::System.Text.Json.Serialization.Metadata.JsonObjectInfoValues() + { + ObjectCreator = null, + ObjectWithParameterizedConstructorCreator = static (args) => new global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.MyLinkedList((global::System.Int32)args[0], (global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.MyLinkedList)args[1]), + PropertyMetadataInitializer = _ => MyLinkedListPropInit(options), + ConstructorParameterMetadataInitializer = MyLinkedListCtorParamInit, + NumberHandling = default, + SerializeHandler = MyLinkedListSerializeHandler + }; + + jsonTypeInfo = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreateObjectInfo(options, objectInfo); + } + + if (makeReadOnly) + { + jsonTypeInfo.MakeReadOnly(); + } + + return jsonTypeInfo; + } + + private static global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[] MyLinkedListPropInit(global::System.Text.Json.JsonSerializerOptions options) + { + global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[] properties = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo[2]; + + global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues info0 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues() + { + IsProperty = true, + IsPublic = true, + IsVirtual = false, + DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.MyLinkedList), + Converter = null, + Getter = static (obj) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.MyLinkedList)obj).Value, + Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.MyLinkedList)obj).Value = value!, + IgnoreCondition = null, + HasJsonInclude = false, + IsExtensionData = false, + NumberHandling = default, + PropertyName = "Value", + JsonPropertyName = null + }; + + global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo0 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo(options, info0); + properties[0] = propertyInfo0; + + global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues info1 = new global::System.Text.Json.Serialization.Metadata.JsonPropertyInfoValues() + { + IsProperty = true, + IsPublic = true, + IsVirtual = false, + DeclaringType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.MyLinkedList), + Converter = null, + Getter = static (obj) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.MyLinkedList)obj).Nested!, + Setter = static (obj, value) => ((global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.MyLinkedList)obj).Nested = value!, + IgnoreCondition = null, + HasJsonInclude = false, + IsExtensionData = false, + NumberHandling = default, + PropertyName = "Nested", + JsonPropertyName = null + }; + + global::System.Text.Json.Serialization.Metadata.JsonPropertyInfo propertyInfo1 = global::System.Text.Json.Serialization.Metadata.JsonMetadataServices.CreatePropertyInfo(options, info1); + properties[1] = propertyInfo1; + + return properties; + } + + // Intentionally not a static method because we create a delegate to it. Invoking delegates to instance + // methods is almost as fast as virtual calls. Static methods need to go through a shuffle thunk. + private void MyLinkedListSerializeHandler(global::System.Text.Json.Utf8JsonWriter writer, global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.MyLinkedList? value) + { + if (value == null) + { + writer.WriteNullValue(); + return; + } + + writer.WriteStartObject(); + writer.WriteNumber(PropName_Value, value.Value); + writer.WritePropertyName(PropName_Nested); + MyLinkedListSerializeHandler(writer, value.Nested!); + + writer.WriteEndObject(); + } + + private static global::System.Text.Json.Serialization.Metadata.JsonParameterInfoValues[] MyLinkedListCtorParamInit() + { + global::System.Text.Json.Serialization.Metadata.JsonParameterInfoValues[] parameters = new global::System.Text.Json.Serialization.Metadata.JsonParameterInfoValues[2]; + global::System.Text.Json.Serialization.Metadata.JsonParameterInfoValues info; + + info = new() + { + Name = "value", + ParameterType = typeof(global::System.Int32), + Position = 0, + HasDefaultValue = false, + DefaultValue = default(global::System.Int32) + }; + parameters[0] = info; + + info = new() + { + Name = "nested", + ParameterType = typeof(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.MyLinkedList), + Position = 1, + HasDefaultValue = false, + DefaultValue = default(global::System.Text.Json.Tests.SourceGenRegressionTests.Net70.MyLinkedList) + }; + parameters[1] = info; + + return parameters; + } + } +} diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70/Net70GeneratedContext.PropertyNames.g.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70/Net70GeneratedContext.PropertyNames.g.cs index d2edcb1433c79c..7ad6a3ba0a5250 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70/Net70GeneratedContext.PropertyNames.g.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70/Net70GeneratedContext.PropertyNames.g.cs @@ -26,5 +26,7 @@ public partial class Net70GeneratedContext private static readonly global::System.Text.Json.JsonEncodedText PropName_SummaryWords = global::System.Text.Json.JsonEncodedText.Encode("SummaryWords"); private static readonly global::System.Text.Json.JsonEncodedText PropName_High = global::System.Text.Json.JsonEncodedText.Encode("High"); private static readonly global::System.Text.Json.JsonEncodedText PropName_Low = global::System.Text.Json.JsonEncodedText.Encode("Low"); + private static readonly global::System.Text.Json.JsonEncodedText PropName_Value = global::System.Text.Json.JsonEncodedText.Encode("Value"); + private static readonly global::System.Text.Json.JsonEncodedText PropName_Nested = global::System.Text.Json.JsonEncodedText.Encode("Nested"); } } diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70/Net70GeneratedContext.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70/Net70GeneratedContext.cs index ebfbbd7c79f07a..bcc9cf20751ecb 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70/Net70GeneratedContext.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70/Net70GeneratedContext.cs @@ -12,6 +12,7 @@ namespace System.Text.Json.Tests.SourceGenRegressionTests.Net70 { //[JsonSerializable(typeof(WeatherForecastWithPOCOs))] //[JsonSerializable(typeof(ClassWithCustomConverter))] + //[JsonSerializable(typeof(MyLinkedList))] public partial class Net70GeneratedContext : JsonSerializerContext { } public class WeatherForecastWithPOCOs @@ -31,6 +32,18 @@ public class HighLowTemps public int Low { get; set; } } + public class MyLinkedList + { + public MyLinkedList(int value, MyLinkedList? nested) + { + Value = value; + Nested = nested; + } + + public int Value { get; set; } + public MyLinkedList? Nested { get; set; } + } + [JsonConverter(typeof(CustomConverter))] public class ClassWithCustomConverter { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70/Net70GeneratedContext.g.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70/Net70GeneratedContext.g.cs index d6427a7c7848b1..daa9d4acb0f14e 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70/Net70GeneratedContext.g.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70/Net70GeneratedContext.g.cs @@ -16,7 +16,7 @@ namespace System.Text.Json.Tests.SourceGenRegressionTests.Net70 { - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Text.Json.SourceGeneration", "7.0.7.1805")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Text.Json.SourceGeneration", "7.0.8.17405")] public partial class Net70GeneratedContext { diff --git a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70RegressionTests.cs b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70RegressionTests.cs index 38c06bc04a2195..af0bcfd73427f9 100644 --- a/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70RegressionTests.cs +++ b/src/libraries/System.Text.Json/tests/System.Text.Json.Tests/SourceGenRegressionTests/Net70RegressionTests.cs @@ -140,6 +140,26 @@ public static void HighLowTemps_ContextReportsCorrectMetadata() Assert.Equal(2, jsonPropertyInfo.Get(instance)); } + [Fact] + public static void SupportsRecursiveTypeSerialization() + { + JsonTypeInfo jsonTypeInfo = Net70GeneratedContext.Default.MyLinkedList; + + MyLinkedList linkedList = new( + value: 0, + nested: new( + value: 1, + nested: new( + value: 2, + nested: null))); + + string json = JsonSerializer.Serialize(linkedList, jsonTypeInfo); + Assert.Equal("""{"Value":0,"Nested":{"Value":1,"Nested":{"Value":2,"Nested":null}}}""", json); + + linkedList = JsonSerializer.Deserialize(json, jsonTypeInfo); + Assert.Equal(2, linkedList.Nested.Nested.Value); + } + [Fact] public static void CombinedContexts_WorksAsExpected() { 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 8d0e4e67d83376..d34d3d1208f8d8 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 @@ -227,6 +227,7 @@ + @@ -241,6 +242,7 @@ + diff --git a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs index 870a3a00888851..8c8831cbd469a2 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs @@ -19,6 +19,7 @@ // Most changes made to this file should be kept in sync, so far as bug fixes and relevant optimizations // are concerned. +#pragma warning disable CA1861 // Avoid constant arrays as arguments. namespace System.Text.RegularExpressions.Generator { public partial class RegexGenerator diff --git a/src/libraries/System.Text.RegularExpressions/gen/UpgradeToGeneratedRegexCodeFixer.cs b/src/libraries/System.Text.RegularExpressions/gen/UpgradeToGeneratedRegexCodeFixer.cs index dc1e6671580854..fd5bfa8d64daf4 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/UpgradeToGeneratedRegexCodeFixer.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/UpgradeToGeneratedRegexCodeFixer.cs @@ -34,6 +34,8 @@ public sealed class UpgradeToGeneratedRegexCodeFixer : CodeFixProvider /// public override ImmutableArray FixableDiagnosticIds => ImmutableArray.Create(DiagnosticDescriptors.UseRegexSourceGeneration.Id); + private static readonly char[] s_comma = new[] { ',' }; + public override FixAllProvider? GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; /// @@ -313,7 +315,7 @@ static string Literal(string stringifiedRegexOptions) // Parse the runtime-generated "Option1, Option2" into each piece and then concat // them back together. - string[] parts = stringifiedRegexOptions.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + string[] parts = stringifiedRegexOptions.Split(s_comma, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < parts.Length; i++) { parts[i] = "RegexOptions." + parts[i].Trim(); diff --git a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/DefaultPartitionedRateLimiter.cs b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/DefaultPartitionedRateLimiter.cs index 3869fb4974a48a..fabf472ef2e5ea 100644 --- a/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/DefaultPartitionedRateLimiter.cs +++ b/src/libraries/System.Threading.RateLimiting/src/System/Threading/RateLimiting/DefaultPartitionedRateLimiter.cs @@ -45,7 +45,6 @@ private DefaultPartitionedRateLimiter(Func> _limiters = new Dictionary>(equalityComparer); _partitioner = partitioner; - // TODO: Figure out what interval we should use _timer = new TimerAwaitable(timerInterval, timerInterval); _timerTask = RunTimer(); } @@ -57,9 +56,14 @@ private async Task RunTimer() { try { - await Heartbeat().ConfigureAwait(false); + await Heartbeat().ConfigureAwait( +#if NET8_0_OR_GREATER + ConfigureAwaitOptions.SuppressThrowing +#else + false +#endif + ); } - // TODO: Can we log to EventSource or somewhere? Maybe dispatch throwing the exception so it is at least an unhandled exception? catch { } } _timer.Dispose(); diff --git a/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/TaskAwaiterTests.cs b/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/TaskAwaiterTests.cs index 94f00ce5338a5c..1a4032119ed972 100644 --- a/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/TaskAwaiterTests.cs +++ b/src/libraries/System.Threading.Tasks/tests/System.Runtime.CompilerServices/TaskAwaiterTests.cs @@ -561,6 +561,108 @@ public static IEnumerable CanceledTasksAndExpectedCancellationExceptio yield return new object[] { LineNumber(), atmb.Task, oce }; } + [Theory] + [InlineData((ConfigureAwaitOptions)0x8)] + public void ConfigureAwaitOptions_Invalid(ConfigureAwaitOptions options) + { + AssertExtensions.Throws("options", () => Task.CompletedTask.ConfigureAwait(options)); + AssertExtensions.Throws("options", () => Task.FromResult(true).ConfigureAwait(options)); + } + + [Fact] + public void ConfigureAwaitOptions_SuppressThrowingUnsupportedOnGenericTask() + { + AssertExtensions.Throws("options", () => Task.FromResult(true).ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing)); + AssertExtensions.Throws("options", () => Task.FromResult(true).ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing | ConfigureAwaitOptions.ForceYielding)); + } + + [Theory] + [InlineData(ConfigureAwaitOptions.ForceYielding)] + [InlineData(ConfigureAwaitOptions.ForceYielding | ConfigureAwaitOptions.ContinueOnCapturedContext)] + [InlineData(ConfigureAwaitOptions.ForceYielding | ConfigureAwaitOptions.SuppressThrowing)] + [InlineData(ConfigureAwaitOptions.ForceYielding | ConfigureAwaitOptions.ContinueOnCapturedContext | ConfigureAwaitOptions.SuppressThrowing)] + public void ConfigureAwaitOptions_ForceYielding_IsCompletedAlwaysFalse(ConfigureAwaitOptions options) + { + Assert.False(new TaskCompletionSource().Task.ConfigureAwait(options).GetAwaiter().IsCompleted); + Assert.False(Task.CompletedTask.ConfigureAwait(options).GetAwaiter().IsCompleted); + + if ((options & ConfigureAwaitOptions.SuppressThrowing) == 0) + { + Assert.False(new TaskCompletionSource().Task.ConfigureAwait(options).GetAwaiter().IsCompleted); + Assert.False(Task.FromResult(42).ConfigureAwait(options).GetAwaiter().IsCompleted); + } + } + + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + public void ConfigureAwaitOptions_SuppressThrowing_NoExceptionsAreThrown() + { + Task t; + + t = Task.FromCanceled(new CancellationToken(true)); + t.ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing).GetAwaiter().GetResult(); + t.ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing | ConfigureAwaitOptions.ForceYielding | ConfigureAwaitOptions.ContinueOnCapturedContext).GetAwaiter().GetResult(); + Assert.ThrowsAny(() => t.ConfigureAwait(ConfigureAwaitOptions.ContinueOnCapturedContext).GetAwaiter().GetResult()); + Assert.ThrowsAny(() => t.ConfigureAwait(ConfigureAwaitOptions.ContinueOnCapturedContext | ConfigureAwaitOptions.ForceYielding).GetAwaiter().GetResult()); + + t = Task.FromException(new FormatException()); + t.ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing).GetAwaiter().GetResult(); + t.ConfigureAwait(ConfigureAwaitOptions.SuppressThrowing | ConfigureAwaitOptions.ForceYielding | ConfigureAwaitOptions.ContinueOnCapturedContext).GetAwaiter().GetResult(); + Assert.Throws(() => t.ConfigureAwait(ConfigureAwaitOptions.ContinueOnCapturedContext).GetAwaiter().GetResult()); + Assert.Throws(() => t.ConfigureAwait(ConfigureAwaitOptions.ContinueOnCapturedContext | ConfigureAwaitOptions.ForceYielding).GetAwaiter().GetResult()); + } + + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] + [InlineData(false, ConfigureAwaitOptions.None)] + [InlineData(false, ConfigureAwaitOptions.ContinueOnCapturedContext)] + [InlineData(true, ConfigureAwaitOptions.None)] + [InlineData(true, ConfigureAwaitOptions.ContinueOnCapturedContext)] + public static void ConfigureAwaitOptions_ContinueOnCapturedContext_QueuesAccordingly(bool generic, ConfigureAwaitOptions options) + { + SynchronizationContext origCtx = SynchronizationContext.Current; + try + { + // Create a context that tracks operations, and set it as current + var validateCtx = new ValidateCorrectContextSynchronizationContext(); + Assert.Equal(0, validateCtx.PostCount); + SynchronizationContext.SetSynchronizationContext(validateCtx); + + // Create a not-completed task and get an awaiter for it + var mres = new ManualResetEventSlim(); + var tcs = new TaskCompletionSource(); + + // Hook up a callback + bool postedInContext = false; + Action callback = () => + { + postedInContext = ValidateCorrectContextSynchronizationContext.t_isPostedInContext; + mres.Set(); + }; + if (generic) + { + tcs.Task.ConfigureAwait(options).GetAwaiter().OnCompleted(callback); + } + else + { + ((Task)tcs.Task).ConfigureAwait(options).GetAwaiter().OnCompleted(callback); + } + Assert.False(mres.IsSet, "Callback should not yet have run."); + + // Complete the task in another context and wait for the callback to run + Task.Run(() => tcs.SetResult(null)); + mres.Wait(); + + // Validate the callback ran and in the correct context + bool shouldHavePosted = options == ConfigureAwaitOptions.ContinueOnCapturedContext; + Assert.Equal(shouldHavePosted ? 1 : 0, validateCtx.PostCount); + Assert.Equal(shouldHavePosted, postedInContext); + } + finally + { + // Reset back to the original context + SynchronizationContext.SetSynchronizationContext(origCtx); + } + } + private static int LineNumber([CallerLineNumber]int lineNumber = 0) => lineNumber; private class ValidateCorrectContextSynchronizationContext : SynchronizationContext diff --git a/src/libraries/System.Threading/tests/InterlockedTests.cs b/src/libraries/System.Threading/tests/InterlockedTests.cs index f47fc99a07ee5b..933404fdbfd76f 100644 --- a/src/libraries/System.Threading/tests/InterlockedTests.cs +++ b/src/libraries/System.Threading/tests/InterlockedTests.cs @@ -9,7 +9,7 @@ namespace System.Threading.Tests { - public class InterlockedTests + public unsafe class InterlockedTests { [Fact] public void InterlockedAdd_Int32() @@ -603,6 +603,23 @@ public void InterlockedAddAndRead_Multithreaded_Int64() Assert.Equal(ThreadCount * IterationCount * Increment, Interlocked.Read(ref value)); } + [MethodImpl(MethodImplOptions.NoInlining)] + private static Action MemoryBarrierDelegate() => Interlocked.MemoryBarrier; + + [MethodImpl(MethodImplOptions.NoInlining)] + private static delegate* MemoryBarrierPointer() => &Interlocked.MemoryBarrier; + + [Fact()] + public void MemoryBarrierIntrinsic() + { + // Interlocked.MemoryBarrier is a self-referring intrinsic + // we should be able to call it through a delegate. + MemoryBarrierDelegate()(); + + // through a method pointer + MemoryBarrierPointer()(); + } + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsThreadingSupported))] public void MemoryBarrierProcessWide() { diff --git a/src/libraries/System.Threading/tests/System.Threading.Tests.csproj b/src/libraries/System.Threading/tests/System.Threading.Tests.csproj index 81ac83a8a221e7..c4bb4f6191835e 100644 --- a/src/libraries/System.Threading/tests/System.Threading.Tests.csproj +++ b/src/libraries/System.Threading/tests/System.Threading.Tests.csproj @@ -3,6 +3,7 @@ true true $(NetCoreAppCurrent) + true diff --git a/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.xml b/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.xml index 2653e1e4d5477c..e3cd7e69fd2dc7 100644 --- a/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.xml +++ b/src/libraries/apicompat/ApiCompatBaseline.NetCoreAppLatestStable.xml @@ -2553,79 +2553,7 @@ CP0015 - M:System.Runtime.Serialization.Formatter.Deserialize(System.IO.Stream):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/mscorlib.dll - net8.0/mscorlib.dll - - - CP0015 - M:System.Runtime.Serialization.Formatter.Serialize(System.IO.Stream,System.Object):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/mscorlib.dll - net8.0/mscorlib.dll - - - CP0015 - M:System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(System.IO.Stream):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/mscorlib.dll - net8.0/mscorlib.dll - - - CP0015 - M:System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(System.IO.Stream,System.Object):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/mscorlib.dll - net8.0/mscorlib.dll - - - CP0015 - M:System.Runtime.Serialization.IFormatter.Deserialize(System.IO.Stream):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/mscorlib.dll - net8.0/mscorlib.dll - - - CP0015 - M:System.Runtime.Serialization.IFormatter.Serialize(System.IO.Stream,System.Object):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/mscorlib.dll - net8.0/mscorlib.dll - - - CP0015 - M:System.Runtime.Serialization.ObjectManager.DoFixups:[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/mscorlib.dll - net8.0/mscorlib.dll - - - CP0015 - M:System.Runtime.Serialization.ObjectManager.RaiseOnDeserializingEvent(System.Object):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/mscorlib.dll - net8.0/mscorlib.dll - - - CP0015 - M:System.Runtime.Serialization.ObjectManager.RegisterObject(System.Object,System.Int64,System.Runtime.Serialization.SerializationInfo,System.Int64,System.Reflection.MemberInfo,System.Int32[]):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/mscorlib.dll - net8.0/mscorlib.dll - - - CP0015 - M:System.Runtime.Serialization.ObjectManager.RegisterObject(System.Object,System.Int64,System.Runtime.Serialization.SerializationInfo,System.Int64,System.Reflection.MemberInfo):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/mscorlib.dll - net8.0/mscorlib.dll - - - CP0015 - M:System.Runtime.Serialization.ObjectManager.RegisterObject(System.Object,System.Int64,System.Runtime.Serialization.SerializationInfo):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/mscorlib.dll - net8.0/mscorlib.dll - - - CP0015 - M:System.Runtime.Serialization.ObjectManager.RegisterObject(System.Object,System.Int64):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/mscorlib.dll - net8.0/mscorlib.dll - - - CP0015 - M:System.Runtime.Serialization.SerializationObjectManager.RegisterObject(System.Object):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] + M:System.Type.GetEnumValues:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] net7.0/mscorlib.dll net8.0/mscorlib.dll @@ -2643,79 +2571,7 @@ CP0015 - M:System.Runtime.Serialization.Formatter.Deserialize(System.IO.Stream):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/netstandard.dll - net8.0/netstandard.dll - - - CP0015 - M:System.Runtime.Serialization.Formatter.Serialize(System.IO.Stream,System.Object):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/netstandard.dll - net8.0/netstandard.dll - - - CP0015 - M:System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(System.IO.Stream):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/netstandard.dll - net8.0/netstandard.dll - - - CP0015 - M:System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(System.IO.Stream,System.Object):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/netstandard.dll - net8.0/netstandard.dll - - - CP0015 - M:System.Runtime.Serialization.IFormatter.Deserialize(System.IO.Stream):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/netstandard.dll - net8.0/netstandard.dll - - - CP0015 - M:System.Runtime.Serialization.IFormatter.Serialize(System.IO.Stream,System.Object):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/netstandard.dll - net8.0/netstandard.dll - - - CP0015 - M:System.Runtime.Serialization.ObjectManager.DoFixups:[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/netstandard.dll - net8.0/netstandard.dll - - - CP0015 - M:System.Runtime.Serialization.ObjectManager.RaiseOnDeserializingEvent(System.Object):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/netstandard.dll - net8.0/netstandard.dll - - - CP0015 - M:System.Runtime.Serialization.ObjectManager.RegisterObject(System.Object,System.Int64,System.Runtime.Serialization.SerializationInfo,System.Int64,System.Reflection.MemberInfo,System.Int32[]):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/netstandard.dll - net8.0/netstandard.dll - - - CP0015 - M:System.Runtime.Serialization.ObjectManager.RegisterObject(System.Object,System.Int64,System.Runtime.Serialization.SerializationInfo,System.Int64,System.Reflection.MemberInfo):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/netstandard.dll - net8.0/netstandard.dll - - - CP0015 - M:System.Runtime.Serialization.ObjectManager.RegisterObject(System.Object,System.Int64,System.Runtime.Serialization.SerializationInfo):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/netstandard.dll - net8.0/netstandard.dll - - - CP0015 - M:System.Runtime.Serialization.ObjectManager.RegisterObject(System.Object,System.Int64):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/netstandard.dll - net8.0/netstandard.dll - - - CP0015 - M:System.Runtime.Serialization.SerializationObjectManager.RegisterObject(System.Object):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] + M:System.Type.GetEnumValues:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] net7.0/netstandard.dll net8.0/netstandard.dll @@ -2761,6 +2617,12 @@ net7.0/System.Linq.Queryable.dll net8.0/System.Linq.Queryable.dll + + CP0015 + M:System.Type.GetEnumValues:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + net7.0/System.Runtime.dll + net8.0/System.Runtime.dll + CP0015 T:System.Runtime.InteropServices.Marshalling.NativeMarshallingAttribute:[T:System.AttributeUsageAttribute] @@ -2781,98 +2643,8 @@ CP0015 - M:System.Runtime.Serialization.Formatter.Deserialize(System.IO.Stream):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/System.Runtime.Serialization.Formatters.dll - net8.0/System.Runtime.Serialization.Formatters.dll - - - CP0015 - M:System.Runtime.Serialization.Formatter.Serialize(System.IO.Stream,System.Object):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/System.Runtime.Serialization.Formatters.dll - net8.0/System.Runtime.Serialization.Formatters.dll - - - CP0015 - M:System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(System.IO.Stream):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/System.Runtime.Serialization.Formatters.dll - net8.0/System.Runtime.Serialization.Formatters.dll - - - CP0015 - M:System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(System.IO.Stream,System.Object):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/System.Runtime.Serialization.Formatters.dll - net8.0/System.Runtime.Serialization.Formatters.dll - - - CP0015 - M:System.Runtime.Serialization.IFormatter.Deserialize(System.IO.Stream):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/System.Runtime.Serialization.Formatters.dll - net8.0/System.Runtime.Serialization.Formatters.dll - - - CP0015 - M:System.Runtime.Serialization.IFormatter.Serialize(System.IO.Stream,System.Object):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/System.Runtime.Serialization.Formatters.dll - net8.0/System.Runtime.Serialization.Formatters.dll - - - CP0015 - M:System.Runtime.Serialization.ObjectManager.DoFixups:[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/System.Runtime.Serialization.Formatters.dll - net8.0/System.Runtime.Serialization.Formatters.dll - - - CP0015 - M:System.Runtime.Serialization.ObjectManager.RaiseOnDeserializingEvent(System.Object):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/System.Runtime.Serialization.Formatters.dll - net8.0/System.Runtime.Serialization.Formatters.dll - - - CP0015 - M:System.Runtime.Serialization.ObjectManager.RegisterObject(System.Object,System.Int64,System.Runtime.Serialization.SerializationInfo,System.Int64,System.Reflection.MemberInfo,System.Int32[]):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/System.Runtime.Serialization.Formatters.dll - net8.0/System.Runtime.Serialization.Formatters.dll - - - CP0015 - M:System.Runtime.Serialization.ObjectManager.RegisterObject(System.Object,System.Int64,System.Runtime.Serialization.SerializationInfo,System.Int64,System.Reflection.MemberInfo):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/System.Runtime.Serialization.Formatters.dll - net8.0/System.Runtime.Serialization.Formatters.dll - - - CP0015 - M:System.Runtime.Serialization.ObjectManager.RegisterObject(System.Object,System.Int64,System.Runtime.Serialization.SerializationInfo):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/System.Runtime.Serialization.Formatters.dll - net8.0/System.Runtime.Serialization.Formatters.dll - - - CP0015 - M:System.Runtime.Serialization.ObjectManager.RegisterObject(System.Object,System.Int64):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/System.Runtime.Serialization.Formatters.dll - net8.0/System.Runtime.Serialization.Formatters.dll - - - CP0015 - M:System.Runtime.Serialization.SerializationObjectManager.RegisterObject(System.Object):[T:System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute] - net7.0/System.Runtime.Serialization.Formatters.dll - net8.0/System.Runtime.Serialization.Formatters.dll - - - CP0015 - M:System.Type.GetEnumValues:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] - net7.0/mscorlib.dll - net8.0/mscorlib.dll - - - CP0015 - M:System.Type.GetEnumValues:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] - net7.0/netstandard.dll - net8.0/netstandard.dll - - - CP0015 - M:System.Type.GetEnumValues:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] - net7.0/System.Runtime.dll - net8.0/System.Runtime.dll + T:System.Text.Json.Serialization.JsonStringEnumConverter:[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + net7.0/System.Text.Json.dll + net8.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 e5f1c7c1332625..44a27d0f8d3f52 100644 --- a/src/libraries/apicompat/ApiCompatBaseline.netstandard2.0.xml +++ b/src/libraries/apicompat/ApiCompatBaseline.netstandard2.0.xml @@ -2761,22 +2761,10 @@ netstandard2.0/netstandard.dll net8.0/netstandard.dll - - CP0015 - T:System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute:[T:System.AttributeUsageAttribute] - netstandard2.0/netstandard.dll - net8.0/netstandard.dll - CP0015 P:System.Timers.Timer.Interval:[T:System.ComponentModel.DefaultValueAttribute] netstandard2.0/System.dll net8.0/System.dll - - CP0015 - T:System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute:[T:System.AttributeUsageAttribute] - netstandard2.0/System.dll - net8.0/System.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 2986cd2e77c4f9..de4ff50c7dc0ed 100644 --- a/src/libraries/apicompat/ApiCompatBaseline.netstandard2.1.xml +++ b/src/libraries/apicompat/ApiCompatBaseline.netstandard2.1.xml @@ -853,12 +853,6 @@ netstandard2.1/netstandard.dll net8.0/netstandard.dll - - CP0015 - T:System.Runtime.CompilerServices.AsyncMethodBuilderAttribute:[T:System.AttributeUsageAttribute] - netstandard2.1/netstandard.dll - net8.0/netstandard.dll - CP0015 T:System.Runtime.InteropServices.ManagedToNativeComInteropStubAttribute:[T:System.AttributeUsageAttribute] diff --git a/src/libraries/shims/System.Data/Directory.Build.props b/src/libraries/shims/System.Data/Directory.Build.props index e3c20fb2ccf083..a051b0fdfeb491 100644 --- a/src/libraries/shims/System.Data/Directory.Build.props +++ b/src/libraries/shims/System.Data/Directory.Build.props @@ -7,7 +7,7 @@ ECMA netcoreapp2.1 - net6.0 + net6.0 diff --git a/src/libraries/tests.proj b/src/libraries/tests.proj index fcbe99e9ea4e2b..32854a84438c93 100644 --- a/src/libraries/tests.proj +++ b/src/libraries/tests.proj @@ -33,7 +33,8 @@ - + + @@ -68,6 +69,9 @@ + + + @@ -408,14 +412,14 @@ + + + + - - - - @@ -505,7 +509,7 @@ - + diff --git a/src/mono/System.Private.CoreLib/src/System/Attribute.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Attribute.Mono.cs index 7cdec768c13add..f885a3560911b2 100644 --- a/src/mono/System.Private.CoreLib/src/System/Attribute.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Attribute.Mono.cs @@ -17,9 +17,10 @@ public partial class Attribute object[] attrs = CustomAttribute.GetCustomAttributes(element, attributeType, inherit); if (attrs == null || attrs.Length == 0) return null; + Attribute match = (Attribute)attrs[0]; if (attrs.Length != 1) - throw new AmbiguousMatchException(); - return (Attribute)(attrs[0]); + throw ThrowHelper.GetAmbiguousMatchException(match); + return match; } public static Attribute? GetCustomAttribute(Assembly element, Type attributeType) => GetAttr(element, attributeType, true); diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.Mono.cs index 8f4729a6e9150a..cb8beb606f1b85 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/Emit/RuntimeTypeBuilder.Mono.cs @@ -431,7 +431,7 @@ protected override void AddInterfaceImplementationCore([DynamicallyAccessedMembe if (types == null) { if (count > 1) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(found!); return found; } MethodBase[] match = new MethodBase[count]; diff --git a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs index ba869161bce87f..42ae4cef4437bd 100644 --- a/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs +++ b/src/mono/System.Private.CoreLib/src/System/Reflection/RuntimeParameterInfo.cs @@ -41,7 +41,7 @@ internal static void FormatParameters(StringBuilder sb, ParameterInfo[] p, Calli // Why don't we just use "&"? if (t.IsByRef) { - sb.Append(typeName.TrimEnd(new char[] { '&' })); + sb.Append(typeName.TrimEnd('&')); sb.Append(" ByRef"); } else @@ -119,6 +119,7 @@ internal RuntimeParameterInfo(Type type, MemberInfo member, MarshalAsAttribute m this.PositionImpl = -1; // since parameter positions are zero-based, return type pos is -1 this.AttrsImpl = ParameterAttributes.Retval; this.marshalAs = marshalAs; + this.DefaultValueImpl = DBNull.Value; } // ctor for no metadata MethodInfo in the DynamicMethod and RuntimeMethodInfo cases 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 014aa965939049..e34b3788e76a8e 100644 --- a/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/RuntimeType.Mono.cs @@ -794,7 +794,7 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) { MethodInfo methodInfo = candidates[j]; if (!System.DefaultBinder.CompareMethodSig(methodInfo, firstCandidate)) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(firstCandidate); } // All the methods have the exact same name and sig so return the most derived one. @@ -850,10 +850,10 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) if (types == null || types.Length == 0) { // no arguments + PropertyInfo firstCandidate = candidates[0]; + if (candidates.Count == 1) { - PropertyInfo firstCandidate = candidates[0]; - if (returnType is not null && !returnType.IsEquivalentTo(firstCandidate.PropertyType)) return null; @@ -863,7 +863,7 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) { if (returnType is null) // if we are here we have no args or property type to select over and we have more than one property with that name - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(firstCandidate); } } @@ -894,7 +894,7 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) if ((bindingAttr & eventInfo.BindingFlags) == eventInfo.BindingFlags) { if (match != null) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(match); match = eventInfo; } @@ -923,7 +923,7 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) if (match != null) { if (ReferenceEquals(fieldInfo.DeclaringType, match.DeclaringType)) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(match); if (match.DeclaringType!.IsInterface && fieldInfo.DeclaringType!.IsInterface) multipleStaticFieldMatches = true; @@ -935,7 +935,7 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) } if (multipleStaticFieldMatches && match!.DeclaringType!.IsInterface) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(match); return match; } @@ -987,7 +987,7 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) if (FilterApplyType(iface, bindingAttr, name, false, ns)) { if (match != null) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(match); match = iface; } @@ -1015,7 +1015,7 @@ public override MemberInfo[] GetMembers(BindingFlags bindingAttr) if (FilterApplyType(nestedType, bindingAttr, name, false, ns)) { if (match != null) - throw new AmbiguousMatchException(); + throw ThrowHelper.GetAmbiguousMatchException(match); match = nestedType; } diff --git a/src/mono/System.Private.CoreLib/src/System/Threading/Interlocked.Mono.cs b/src/mono/System.Private.CoreLib/src/System/Threading/Interlocked.Mono.cs index 8b8daae4b3977f..b5282beaa785d9 100644 --- a/src/mono/System.Private.CoreLib/src/System/Threading/Interlocked.Mono.cs +++ b/src/mono/System.Private.CoreLib/src/System/Threading/Interlocked.Mono.cs @@ -37,9 +37,6 @@ public static partial class Interlocked return result; } - [MethodImplAttribute(MethodImplOptions.InternalCall)] - public static extern float CompareExchange(ref float location1, float value, float comparand); - [Intrinsic] [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern int Decrement(ref int location); @@ -72,16 +69,9 @@ public static partial class Interlocked return result; } - [Intrinsic] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - public static extern float Exchange(ref float location1, float value); - [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern long CompareExchange(ref long location1, long value, long comparand); - [MethodImplAttribute(MethodImplOptions.InternalCall)] - public static extern double CompareExchange(ref double location1, double value, double comparand); - [return: NotNullIfNotNull(nameof(location1))] [Intrinsic] public static T CompareExchange(ref T location1, T value, T comparand) where T : class? @@ -110,10 +100,6 @@ public static T CompareExchange(ref T location1, T value, T comparand) where [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern long Exchange(ref long location1, long value); - [Intrinsic] - [MethodImplAttribute(MethodImplOptions.InternalCall)] - public static extern double Exchange(ref double location1, double value); - [return: NotNullIfNotNull(nameof(location1))] [Intrinsic] public static T Exchange([NotNullIfNotNull(nameof(value))] ref T location1, T value) where T : class? @@ -145,11 +131,6 @@ public static T Exchange([NotNullIfNotNull(nameof(value))] ref T location1, T [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern long Add(ref long location1, long value); - [Intrinsic] - public static void MemoryBarrier() - { - } - [MethodImplAttribute(MethodImplOptions.InternalCall)] public static extern void MemoryBarrierProcessWide(); } diff --git a/src/mono/mono/metadata/class-accessors.c b/src/mono/mono/metadata/class-accessors.c index 4cc08da084bafc..f74b2dc4dbe704 100644 --- a/src/mono/mono/metadata/class-accessors.c +++ b/src/mono/mono/metadata/class-accessors.c @@ -578,6 +578,23 @@ mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error) return TRUE; } +/** + * mono_class_set_deferred_failure: + * \param klass class in which the failure was detected + + * This method marks the class with a deferred failure, indicating that a failure was detected but it will be processed during AOT runtime.. + * Note that only the first failure is kept. + * + * LOCKING: Acquires the loader lock. + */ +void +mono_class_set_deferred_failure (MonoClass *klass) +{ + mono_loader_lock (); + klass->has_deferred_failure = 1; + mono_loader_unlock (); +} + /** * mono_class_set_nonblittable: * \param klass class which will be marked as not blittable. diff --git a/src/mono/mono/metadata/class-getters.h b/src/mono/mono/metadata/class-getters.h index 9eafbb4330bc84..c0e15059991ad6 100644 --- a/src/mono/mono/metadata/class-getters.h +++ b/src/mono/mono/metadata/class-getters.h @@ -49,6 +49,7 @@ 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_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) MONO_CLASS_GETTER(m_class_has_dim_conflicts, gboolean, , MonoClass, has_dim_conflicts) MONO_CLASS_GETTER(m_class_get_parent, MonoClass *, , MonoClass, parent) diff --git a/src/mono/mono/metadata/class-init.c b/src/mono/mono/metadata/class-init.c index dca64cab11ce04..c41ea7b891d4cb 100644 --- a/src/mono/mono/metadata/class-init.c +++ b/src/mono/mono/metadata/class-init.c @@ -304,8 +304,12 @@ mono_class_setup_fields (MonoClass *klass) instance_size = MONO_ABI_SIZEOF (MonoObject); } - if (m_class_is_inlinearray (klass) && m_class_inlinearray_value (klass) <= 0) - mono_class_set_type_load_failure (klass, "Inline array length property must be positive."); + if (m_class_is_inlinearray (klass) && m_class_inlinearray_value (klass) <= 0) { + if (mono_get_runtime_callbacks ()->mono_class_set_deferred_type_load_failure_callback) + mono_get_runtime_callbacks ()->mono_class_set_deferred_type_load_failure_callback (klass, "Inline array length property must be positive."); + else + mono_class_set_type_load_failure (klass, "Inline array length property must be positive."); + } /* Get the real size */ explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size); @@ -376,8 +380,15 @@ mono_class_setup_fields (MonoClass *klass) break; } if (m_class_is_inlinearray (klass)) { - mono_class_set_type_load_failure (klass, "Inline array struct must not have explicit layout."); - break; + if (mono_get_runtime_callbacks ()->mono_class_set_deferred_type_load_failure_callback) { + if (mono_get_runtime_callbacks ()->mono_class_set_deferred_type_load_failure_callback (klass, "Inline array struct must not have explicit layout.")) + break; + else + ; // failure occured during AOT compilation, continue execution + } else { + mono_class_set_type_load_failure (klass, "Inline array struct must not have explicit layout."); + break; + } } } if (mono_type_has_exceptions (field->type)) { @@ -2276,12 +2287,20 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ if (m_class_is_inlinearray (klass)) { // Limit the max size of array instance to 1MiB const guint32 struct_max_size = 1024 * 1024; + guint32 initial_size = size; // If size overflows, it returns 0 size *= m_class_inlinearray_value (klass); inlined_fields++; if(size == 0 || size > struct_max_size) { - mono_class_set_type_load_failure (klass, "Inline array struct size out of bounds, abnormally large."); - break; + if (mono_get_runtime_callbacks ()->mono_class_set_deferred_type_load_failure_callback) { + if (mono_get_runtime_callbacks ()->mono_class_set_deferred_type_load_failure_callback (klass, "Inline array struct size out of bounds, abnormally large.")) + break; + else + size = initial_size; // failure occured during AOT compilation, continue execution + } else { + mono_class_set_type_load_failure (klass, "Inline array struct size out of bounds, abnormally large."); + break; + } } } @@ -2311,8 +2330,12 @@ mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_ instance_size &= ~(min_align - 1); } } - if (m_class_is_inlinearray (klass) && inlined_fields != 1) - mono_class_set_type_load_failure (klass, "Inline array struct must have a single field."); + if (m_class_is_inlinearray (klass) && inlined_fields != 1) { + if (mono_get_runtime_callbacks ()->mono_class_set_deferred_type_load_failure_callback) + mono_get_runtime_callbacks ()->mono_class_set_deferred_type_load_failure_callback (klass, "Inline array struct must have a single field."); + else + mono_class_set_type_load_failure (klass, "Inline array struct must have a single field."); + } break; case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: { real_size = 0; @@ -2993,6 +3016,14 @@ mono_class_init_internal (MonoClass *klass) has_cached_info = mono_class_get_cached_class_info (klass, &cached_info); + /* + * If the class has a deferred failure, ignore the cached info and + * let the runtime go on the slow path of trying to setup the class + * layout at runtime. + */ + if (has_cached_info && cached_info.has_deferred_failure) + has_cached_info = FALSE; + /* Compute instance size etc. */ init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL); if (mono_class_has_failure (klass)) diff --git a/src/mono/mono/metadata/class-internals.h b/src/mono/mono/metadata/class-internals.h index 7915be4ed11839..68f83b16ab2fca 100644 --- a/src/mono/mono/metadata/class-internals.h +++ b/src/mono/mono/metadata/class-internals.h @@ -578,6 +578,7 @@ typedef struct MonoCachedClassInfo { guint no_special_static_fields : 1; guint is_generic_container : 1; guint has_weak_fields : 1; + guint has_deferred_failure : 1; guint32 cctor_token; MonoImage *finalize_image; guint32 finalize_token; @@ -1062,9 +1063,6 @@ mono_register_jit_icall_info (MonoJitICallInfo *info, T func, const char *name, #define mono_register_jit_icall(func, sig, no_wrapper) (mono_register_jit_icall_info (&mono_get_jit_icall_info ()->func, func, #func, (sig), (no_wrapper), NULL)) -gboolean -mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...) MONO_ATTR_FORMAT_PRINTF(2,3); - MonoException* mono_class_get_exception_for_failure (MonoClass *klass); @@ -1268,6 +1266,9 @@ mono_error_set_for_class_failure (MonoError *orerror, const MonoClass *klass); gboolean mono_class_has_failure (const MonoClass *klass); +gboolean +mono_class_has_deferred_failure (const MonoClass *klass); + /* Kind specific accessors */ MONO_COMPONENT_API MonoGenericClass* mono_class_get_generic_class (MonoClass *klass); @@ -1429,6 +1430,9 @@ mono_class_find_enum_basetype (MonoClass *klass, MonoError *error); gboolean mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error); +void +mono_class_set_deferred_failure (MonoClass *klass); + gboolean mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg); diff --git a/src/mono/mono/metadata/class-private-definition.h b/src/mono/mono/metadata/class-private-definition.h index 08139a219c6934..ee104bb40a6668 100644 --- a/src/mono/mono/metadata/class-private-definition.h +++ b/src/mono/mono/metadata/class-private-definition.h @@ -83,6 +83,7 @@ struct _MonoClass { guint has_weak_fields : 1; /* class has weak reference fields */ 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; MonoClass *parent; MonoClass *nested_in; diff --git a/src/mono/mono/metadata/class.c b/src/mono/mono/metadata/class.c index 5dc37fc02f8462..053a13ccc71bf4 100644 --- a/src/mono/mono/metadata/class.c +++ b/src/mono/mono/metadata/class.c @@ -5943,36 +5943,11 @@ mono_class_has_failure (const MonoClass *klass) return m_class_has_failure ((MonoClass*)klass) != 0; } - -/** - * mono_class_set_type_load_failure: - * \param klass class in which the failure was detected - * \param fmt \c printf -style error message string. - * - * Collect detected failure informaion in the class for later processing. - * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class() - * Note that only the first failure is kept. - * - * LOCKING: Acquires the loader lock. - * - * \returns FALSE if a failure was already set on the class, or TRUE otherwise. - */ gboolean -mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...) +mono_class_has_deferred_failure (const MonoClass *klass) { - ERROR_DECL (prepare_error); - va_list args; - - if (mono_class_has_failure (klass)) - return FALSE; - - va_start (args, fmt); - mono_error_vset_type_load_class (prepare_error, klass, fmt, args); - va_end (args); - - MonoErrorBoxed *box = mono_error_box (prepare_error, m_class_get_image (klass)); - mono_error_cleanup (prepare_error); - return mono_class_set_failure (klass, box); + g_assert (klass != NULL); + return m_class_has_deferred_failure ((MonoClass*)klass) != 0; } /** @@ -6911,3 +6886,77 @@ mono_class_has_default_constructor (MonoClass *klass, gboolean public_only) } return FALSE; } + +/** + * mono_class_set_deferred_type_load_failure: + * \param klass class in which the failure was detected + * \param fmt \c printf -style error message string. + * + * Sets a deferred failure in the class and prints a warning message. + * The deferred failure allows the runtime to attempt setting up the class layout at runtime. + * + * LOCKING: Acquires the loader lock. + * + * \returns FALSE + */ +gboolean +mono_class_set_deferred_type_load_failure (MonoClass *klass, const char * fmt, ...) +{ + if (!mono_class_has_deferred_failure (klass)) { + va_list args; + + va_start (args, fmt); + g_warning ("Warning: %s", fmt, args); + va_end (args); + + mono_class_set_deferred_failure (klass); + } + + return FALSE; +} + +/** + * mono_class_set_type_load_failure: + * \param klass class in which the failure was detected + * \param fmt \c printf -style error message string. + * + * Collect detected failure informaion in the class for later processing. + * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class() + * Note that only the first failure is kept. + * + * LOCKING: Acquires the loader lock. + * + * \returns TRUE + */ +gboolean +mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...) +{ + if (!mono_class_has_failure (klass)) { + ERROR_DECL (prepare_error); + va_list args; + + va_start (args, fmt); + mono_error_vset_type_load_class (prepare_error, klass, fmt, args); + va_end (args); + + MonoErrorBoxed *box = mono_error_box (prepare_error, m_class_get_image (klass)); + mono_error_cleanup (prepare_error); + mono_class_set_failure (klass, box); + } + + return TRUE; +} + +void mono_set_failure_type (MonoFailureType failure_type) { + switch (failure_type) { + case MONO_CLASS_LOADER_IMMEDIATE_FAILURE: + mono_get_runtime_callbacks ()->mono_class_set_deferred_type_load_failure_callback = mono_class_set_type_load_failure; + break; + case MONO_CLASS_LOADER_DEFERRED_FAILURE: + mono_get_runtime_callbacks ()->mono_class_set_deferred_type_load_failure_callback = mono_class_set_deferred_type_load_failure; + break; + default: + g_assert_not_reached(); + break; + } +} diff --git a/src/mono/mono/metadata/icall-def.h b/src/mono/mono/metadata/icall-def.h index 3fc1a6e1cebf62..a2ed4f55f80891 100644 --- a/src/mono/mono/metadata/icall-def.h +++ b/src/mono/mono/metadata/icall-def.h @@ -549,19 +549,15 @@ HANDLES(STRING_11, "InternalIsInterned", ves_icall_System_String_InternalIsInter ICALL_TYPE(ILOCK, "System.Threading.Interlocked", ILOCK_1) NOHANDLES(ICALL(ILOCK_1, "Add(int&,int)", ves_icall_System_Threading_Interlocked_Add_Int)) NOHANDLES(ICALL(ILOCK_2, "Add(long&,long)", ves_icall_System_Threading_Interlocked_Add_Long)) -NOHANDLES(ICALL(ILOCK_4, "CompareExchange(double&,double,double)", ves_icall_System_Threading_Interlocked_CompareExchange_Double)) NOHANDLES(ICALL(ILOCK_5, "CompareExchange(int&,int,int)", ves_icall_System_Threading_Interlocked_CompareExchange_Int)) NOHANDLES(ICALL(ILOCK_6, "CompareExchange(int&,int,int,bool&)", ves_icall_System_Threading_Interlocked_CompareExchange_Int_Success)) NOHANDLES(ICALL(ILOCK_8, "CompareExchange(long&,long,long)", ves_icall_System_Threading_Interlocked_CompareExchange_Long)) NOHANDLES(ICALL(ILOCK_9, "CompareExchange(object&,object&,object&,object&)", ves_icall_System_Threading_Interlocked_CompareExchange_Object)) -NOHANDLES(ICALL(ILOCK_10, "CompareExchange(single&,single,single)", ves_icall_System_Threading_Interlocked_CompareExchange_Single)) NOHANDLES(ICALL(ILOCK_11, "Decrement(int&)", ves_icall_System_Threading_Interlocked_Decrement_Int)) NOHANDLES(ICALL(ILOCK_12, "Decrement(long&)", ves_icall_System_Threading_Interlocked_Decrement_Long)) -NOHANDLES(ICALL(ILOCK_14, "Exchange(double&,double)", ves_icall_System_Threading_Interlocked_Exchange_Double)) NOHANDLES(ICALL(ILOCK_15, "Exchange(int&,int)", ves_icall_System_Threading_Interlocked_Exchange_Int)) NOHANDLES(ICALL(ILOCK_17, "Exchange(long&,long)", ves_icall_System_Threading_Interlocked_Exchange_Long)) NOHANDLES(ICALL(ILOCK_18, "Exchange(object&,object&,object&)", ves_icall_System_Threading_Interlocked_Exchange_Object)) -NOHANDLES(ICALL(ILOCK_19, "Exchange(single&,single)", ves_icall_System_Threading_Interlocked_Exchange_Single)) NOHANDLES(ICALL(ILOCK_20, "Increment(int&)", ves_icall_System_Threading_Interlocked_Increment_Int)) NOHANDLES(ICALL(ILOCK_21, "Increment(long&)", ves_icall_System_Threading_Interlocked_Increment_Long)) NOHANDLES(ICALL(ILOCK_22, "MemoryBarrierProcessWide", ves_icall_System_Threading_Interlocked_MemoryBarrierProcessWide)) diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index 0a7dbc9749595c..a4ec470a2ddb62 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -985,7 +985,7 @@ ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetSpanDataFrom (MonoCl return NULL; } - MonoType *type = targetTypeHandle; + MonoType *type = mono_type_get_underlying_type (targetTypeHandle); if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) { mono_error_set_argument (error, "array", "Cannot initialize array of non-primitive type"); return NULL; diff --git a/src/mono/mono/metadata/metadata-internals.h b/src/mono/mono/metadata/metadata-internals.h index 99aa04e237452c..98896b1c9ccc27 100644 --- a/src/mono/mono/metadata/metadata-internals.h +++ b/src/mono/mono/metadata/metadata-internals.h @@ -682,6 +682,11 @@ typedef struct { #define MONO_SIZEOF_METHOD_SIGNATURE (sizeof (struct _MonoMethodSignature) - MONO_ZERO_LEN_ARRAY * SIZEOF_VOID_P) +typedef enum { + MONO_CLASS_LOADER_IMMEDIATE_FAILURE, // Used during runtime to indicate that the failure should be reported + MONO_CLASS_LOADER_DEFERRED_FAILURE // Used during AOT compilation to defer failure for execution +} MonoFailureType; + static inline gboolean image_is_dynamic (MonoImage *image) { @@ -1257,4 +1262,13 @@ mono_metadata_table_to_ptr_table (int table_num) uint32_t mono_metadata_get_method_params (MonoImage *image, uint32_t method_idx, uint32_t *last_param_out); +void +mono_set_failure_type (MonoFailureType failure_type); + +gboolean +mono_class_set_deferred_type_load_failure (MonoClass *klass, const char * fmt, ...); + +gboolean +mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...); + #endif /* __MONO_METADATA_INTERNALS_H__ */ diff --git a/src/mono/mono/metadata/object-internals.h b/src/mono/mono/metadata/object-internals.h index da9c7628e7c5e2..2f62c2530e8e46 100644 --- a/src/mono/mono/metadata/object-internals.h +++ b/src/mono/mono/metadata/object-internals.h @@ -742,6 +742,19 @@ typedef struct { gboolean (*get_class_from_name) (MonoImage *image, const char *name_space, const char *name, MonoClass **res); gpointer (*build_imt_trampoline) (MonoVTable *vtable, MonoIMTCheckItem **imt_entries, int count, gpointer fail_trunk); MonoJitInfo *(*find_jit_info_in_aot) (MonoImage *image, gpointer addr); + /** + * mono_class_set_deferred_type_load_failure_callback: + * @param klass: Class in which the failure was detected. + * @param fmt: printf-style error message string. + * + * The callback is responsible for processing the failure information provided by the @klass parameter and the error message format string @fmt. + * If a deferred failure occurs, the callback should return FALSE to let the AOT compiler proceed with the class layout setup. + * Otherwise, if the callback returns TRUE, it indicates that the failure should be reported. + * + * @returns: TRUE if the failure is handled and the runtime should not proceed with class setup, FALSE if the failure should be deferred for runtime class setup. + * + */ + gboolean (*mono_class_set_deferred_type_load_failure_callback) (MonoClass *klass, const char * fmt, ...) MONO_ATTR_FORMAT_PRINTF(2,3); } MonoRuntimeCallbacks; typedef gboolean (*MonoInternalStackWalk) (MonoStackFrameInfo *frame, MonoContext *ctx, gpointer data); diff --git a/src/mono/mono/metadata/threads-types.h b/src/mono/mono/metadata/threads-types.h index 5e89f84bef211a..c1436094559c8c 100644 --- a/src/mono/mono/metadata/threads-types.h +++ b/src/mono/mono/metadata/threads-types.h @@ -145,12 +145,6 @@ gint64 ves_icall_System_Threading_Interlocked_Exchange_Long(gint64 *location, gi ICALL_EXPORT void ves_icall_System_Threading_Interlocked_Exchange_Object (MonoObject *volatile*location, MonoObject *volatile*value, MonoObject *volatile*res); -ICALL_EXPORT -gfloat ves_icall_System_Threading_Interlocked_Exchange_Single(gfloat *location, gfloat value); - -ICALL_EXPORT -gdouble ves_icall_System_Threading_Interlocked_Exchange_Double(gdouble *location, gdouble value); - ICALL_EXPORT gint32 ves_icall_System_Threading_Interlocked_CompareExchange_Int(gint32 *location, gint32 value, gint32 comparand); @@ -163,12 +157,6 @@ gint64 ves_icall_System_Threading_Interlocked_CompareExchange_Long(gint64 *locat ICALL_EXPORT void ves_icall_System_Threading_Interlocked_CompareExchange_Object (MonoObject *volatile*location, MonoObject *volatile*value, MonoObject *volatile*comparand, MonoObject *volatile*res); -ICALL_EXPORT -gfloat ves_icall_System_Threading_Interlocked_CompareExchange_Single(gfloat *location, gfloat value, gfloat comparand); - -ICALL_EXPORT -gdouble ves_icall_System_Threading_Interlocked_CompareExchange_Double(gdouble *location, gdouble value, gdouble comparand); - ICALL_EXPORT gint32 ves_icall_System_Threading_Interlocked_Add_Int(gint32 *location, gint32 value); diff --git a/src/mono/mono/metadata/threads.c b/src/mono/mono/metadata/threads.c index 0788d9ccdac13c..7cde95a9dc0b1a 100644 --- a/src/mono/mono/metadata/threads.c +++ b/src/mono/mono/metadata/threads.c @@ -116,16 +116,6 @@ mono_native_thread_join_handle (HANDLE thread_handle, gboolean close_handle); #define LOCK_THREAD(thread) lock_thread((thread)) #define UNLOCK_THREAD(thread) unlock_thread((thread)) -typedef union { - gint32 ival; - gfloat fval; -} IntFloatUnion; - -typedef union { - gint64 ival; - gdouble fval; -} LongDoubleUnion; - typedef struct _StaticDataFreeList StaticDataFreeList; struct _StaticDataFreeList { StaticDataFreeList *next; @@ -2178,18 +2168,6 @@ ves_icall_System_Threading_Interlocked_Exchange_Object (MonoObject *volatile*loc mono_gc_wbarrier_generic_nostore_internal ((gpointer)location); // FIXME volatile } -gfloat ves_icall_System_Threading_Interlocked_Exchange_Single (gfloat *location, gfloat value) -{ - IntFloatUnion val, ret; - if (G_UNLIKELY (!location)) - return (gfloat)set_pending_null_reference_exception (); - - val.fval = value; - ret.ival = mono_atomic_xchg_i32((gint32 *) location, val.ival); - - return ret.fval; -} - gint64 ves_icall_System_Threading_Interlocked_Exchange_Long (gint64 *location, gint64 value) { @@ -2209,19 +2187,6 @@ ves_icall_System_Threading_Interlocked_Exchange_Long (gint64 *location, gint64 v return mono_atomic_xchg_i64 (location, value); } -gdouble -ves_icall_System_Threading_Interlocked_Exchange_Double (gdouble *location, gdouble value) -{ - LongDoubleUnion val, ret; - if (G_UNLIKELY (!location)) - return (gdouble)set_pending_null_reference_exception (); - - val.fval = value; - ret.ival = (gint64)mono_atomic_xchg_i64((gint64 *) location, val.ival); - - return ret.fval; -} - gint32 ves_icall_System_Threading_Interlocked_CompareExchange_Int(gint32 *location, gint32 value, gint32 comparand) { if (G_UNLIKELY (!location)) @@ -2261,46 +2226,6 @@ ves_icall_System_Threading_Interlocked_CompareExchange_Object (MonoObject *volat mono_gc_wbarrier_generic_nostore_internal ((gpointer)location); // FIXME volatile } -gfloat ves_icall_System_Threading_Interlocked_CompareExchange_Single (gfloat *location, gfloat value, gfloat comparand) -{ - IntFloatUnion val, ret, cmp; - if (G_UNLIKELY (!location)) - return (gfloat)set_pending_null_reference_exception (); - - val.fval = value; - cmp.fval = comparand; - ret.ival = mono_atomic_cas_i32((gint32 *) location, val.ival, cmp.ival); - - return ret.fval; -} - -gdouble -ves_icall_System_Threading_Interlocked_CompareExchange_Double (gdouble *location, gdouble value, gdouble comparand) -{ - if (G_UNLIKELY (!location)) - return (gdouble)set_pending_null_reference_exception (); - -#if SIZEOF_VOID_P == 8 - LongDoubleUnion val, comp, ret; - - val.fval = value; - comp.fval = comparand; - ret.ival = (gint64)mono_atomic_cas_ptr((gpointer *) location, (gpointer)val.ival, (gpointer)comp.ival); - - return ret.fval; -#else - gdouble old; - - mono_interlocked_lock (); - old = *location; - if (old == comparand) - *location = value; - mono_interlocked_unlock (); - - return old; -#endif -} - gint64 ves_icall_System_Threading_Interlocked_CompareExchange_Long (gint64 *location, gint64 value, gint64 comparand) { diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 33d4e9db4f01bc..31feac1cc2e054 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -4334,9 +4334,6 @@ collect_dedup_method (MonoAotCompile *acfg, MonoMethod *method) static int add_method_full (MonoAotCompile *acfg, MonoMethod *method, gboolean extra, int depth) { - if (collect_dedup_method (acfg, method)) - return -1; - int index; index = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_indexes, method)); @@ -4423,6 +4420,9 @@ add_extra_method_full (MonoAotCompile *acfg, MonoMethod *method, gboolean prefer mono_error_assert_ok (error); } + if (collect_dedup_method (acfg, method)) + return; + if (acfg->aot_opts.log_generics) aot_printf (acfg, "%*sAdding method %s.\n", depth, "", mono_method_get_full_name (method)); @@ -7880,7 +7880,7 @@ emit_klass_info (MonoAotCompile *acfg, guint32 token) } else { gboolean has_nested = mono_class_get_nested_classes_property (klass) != NULL; encode_value (m_class_get_vtable_size (klass), p, &p); - encode_value ((m_class_has_weak_fields (klass) << 9) | (mono_class_is_gtd (klass) ? (1 << 8) : 0) | (no_special_static << 7) | (m_class_has_static_refs (klass) << 6) | (m_class_has_references (klass) << 5) | ((m_class_is_blittable (klass) << 4) | (has_nested ? 1 : 0) << 3) | (m_class_has_cctor (klass) << 2) | (m_class_has_finalize (klass) << 1) | m_class_is_ghcimpl (klass), p, &p); + encode_value ((m_class_has_deferred_failure (klass) << 10) | (m_class_has_weak_fields (klass) << 9) | (mono_class_is_gtd (klass) ? (1 << 8) : 0) | (no_special_static << 7) | (m_class_has_static_refs (klass) << 6) | (m_class_has_references (klass) << 5) | ((m_class_is_blittable (klass) << 4) | (has_nested ? 1 : 0) << 3) | (m_class_has_cctor (klass) << 2) | (m_class_has_finalize (klass) << 1) | m_class_is_ghcimpl (klass), p, &p); if (m_class_has_cctor (klass)) encode_method_ref (acfg, mono_class_get_cctor (klass), p, &p); if (m_class_has_finalize (klass)) diff --git a/src/mono/mono/mini/aot-runtime.c b/src/mono/mono/mini/aot-runtime.c index 6da9d27bfc8021..65d9770df555ae 100644 --- a/src/mono/mono/mini/aot-runtime.c +++ b/src/mono/mono/mini/aot-runtime.c @@ -2508,6 +2508,7 @@ decode_cached_class_info (MonoAotModule *module, MonoCachedClassInfo *info, guin info->no_special_static_fields = (flags >> 7) & 0x1; info->is_generic_container = (flags >> 8) & 0x1; info->has_weak_fields = (flags >> 9) & 0x1; + info->has_deferred_failure = (flags >> 10) & 0x1; if (info->has_cctor) { res = decode_method_ref (module, &ref, buf, &buf, error); @@ -4555,7 +4556,12 @@ mono_aot_can_dedup (MonoMethod *method) /* Use a set of wrappers/instances which work and useful */ switch (method->wrapper_type) { case MONO_WRAPPER_RUNTIME_INVOKE: +#ifdef TARGET_WASM return TRUE; +#else + return FALSE; +#endif + break; case MONO_WRAPPER_OTHER: { WrapperInfo *info = mono_marshal_get_wrapper_info (method); diff --git a/src/mono/mono/mini/driver.c b/src/mono/mono/mini/driver.c index a5c95bd8ae56be..fd77f6c803551b 100644 --- a/src/mono/mono/mini/driver.c +++ b/src/mono/mono/mini/driver.c @@ -1400,7 +1400,7 @@ main_thread_handler (gpointer user_data) MonoAssembly **assemblies; assemblies = g_new0 (MonoAssembly*, main_args->argc); - + mono_set_failure_type (MONO_CLASS_LOADER_DEFERRED_FAILURE); /* Treat the other arguments as assemblies to compile too */ for (i = 0; i < main_args->argc; ++i) { assembly = mono_domain_assembly_open_internal (mono_alc_get_default (), main_args->argv [i]); diff --git a/src/mono/mono/mini/interp/interp-simd-intrins.def b/src/mono/mono/mini/interp/interp-simd-intrins.def index 0f6973508ae1f9..68f535c70fc495 100644 --- a/src/mono/mono/mini/interp/interp-simd-intrins.def +++ b/src/mono/mono/mini/interp/interp-simd-intrins.def @@ -115,7 +115,8 @@ INTERP_SIMD_INTRINSIC_P_PP (INTERP_SIMD_INTRINSIC_V128_AND_NOT, interp_v128_and_ INTERP_SIMD_INTRINSIC_P_PP (INTERP_SIMD_INTRINSIC_V128_U2_LESS_THAN_EQUAL, interp_v128_u2_less_than_equal, 52) // wasm only has a swizzle opcode for i8x16, none of the others -INTERP_SIMD_INTRINSIC_P_PP (INTERP_SIMD_INTRINSIC_V128_I1_SHUFFLE, interp_v128_i1_shuffle, 14) +// jiterp has special handling for i1 shuffles to secure a v8 optimization +INTERP_SIMD_INTRINSIC_P_PP (INTERP_SIMD_INTRINSIC_V128_I1_SHUFFLE, interp_v128_i1_shuffle, 0) INTERP_SIMD_INTRINSIC_P_PP (INTERP_SIMD_INTRINSIC_V128_I2_SHUFFLE, interp_v128_i2_shuffle, 0) INTERP_SIMD_INTRINSIC_P_PP (INTERP_SIMD_INTRINSIC_V128_I4_SHUFFLE, interp_v128_i4_shuffle, 0) INTERP_SIMD_INTRINSIC_P_PP (INTERP_SIMD_INTRINSIC_V128_I8_SHUFFLE, interp_v128_i8_shuffle, 0) diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index d85d306142e99b..a6ee9e1f3eeaf5 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -8717,6 +8717,7 @@ mono_jiterp_frame_data_allocator_alloc (FrameDataAllocator *stack, InterpFrame * return frame_data_allocator_alloc(stack, frame, size); } +// NOTE: This does not perform a null check and passing a null object or klass is an error! MONO_ALWAYS_INLINE gboolean mono_jiterp_isinst (MonoObject* object, MonoClass* klass) { diff --git a/src/mono/mono/mini/interp/jiterpreter.c b/src/mono/mono/mini/interp/jiterpreter.c index 5133210f744577..af06e5c658b0cd 100644 --- a/src/mono/mono/mini/interp/jiterpreter.c +++ b/src/mono/mono/mini/interp/jiterpreter.c @@ -30,6 +30,7 @@ void jiterp_preserve_module (void); #include #include #include +#include #include "interp.h" #include "interp-internals.h" @@ -163,29 +164,6 @@ mono_jiterp_object_unbox (MonoObject *obj) { return mono_object_unbox_internal(obj); } -EMSCRIPTEN_KEEPALIVE int -mono_jiterp_try_unbox_ref ( - MonoClass *klass, void **dest, MonoObject **src -) { - if (!klass) - return 0; - - MonoObject *o = *src; - if (!o) - return 0; - - if ( - !( - (m_class_get_rank (o->vtable->klass) == 0) && - (m_class_get_element_class (o->vtable->klass) == m_class_get_element_class (klass)) - ) - ) - return 0; - - *dest = mono_object_unbox_internal(o); - return 1; -} - EMSCRIPTEN_KEEPALIVE int mono_jiterp_type_is_byref (MonoType *type) { if (!type) @@ -234,82 +212,63 @@ mono_jiterp_gettype_ref ( } EMSCRIPTEN_KEEPALIVE int -mono_jiterp_cast_ref ( - MonoObject **destination, MonoObject **source, - MonoClass *klass, MintOpcode opcode +mono_jiterp_has_parent_fast ( + MonoClass *klass, MonoClass *parent ) { - if (!klass) - return 0; + // klass may be 0 if null check fusion is active, but that's fine: + // (m_class_get_idepth (0) >= m_class_get_idepth (parent)) in the fast check + // will fail since the idepth of the null ptr is going to be 0, and + // we know parent->idepth >= 1 due to the [m_class_get_idepth (parent) - 1] + return mono_class_has_parent_fast (klass, parent); +} - MonoObject *obj = *source; - if (!obj) { - *destination = 0; - return 1; - } +EMSCRIPTEN_KEEPALIVE int +mono_jiterp_implements_interface ( + MonoVTable *vtable, MonoClass *klass +) { + // If null check fusion is active, vtable->max_interface_id will be 0 + return MONO_VTABLE_IMPLEMENTS_INTERFACE (vtable, m_class_get_interface_id (klass)); +} - switch (opcode) { - case MINT_CASTCLASS: - case MINT_ISINST: { - if (obj) { - // FIXME push/pop LMF - if (!mono_jiterp_isinst (obj, klass)) { // FIXME: do not swallow the error - if (opcode == MINT_ISINST) - *destination = NULL; - else - return 0; // bailout - } else { - *destination = obj; - } - } else { - *destination = NULL; - } - return 1; - } - case MINT_CASTCLASS_INTERFACE: - case MINT_ISINST_INTERFACE: { - gboolean isinst; - // FIXME: Perform some of this work at JIT time - if (MONO_VTABLE_IMPLEMENTS_INTERFACE (obj->vtable, m_class_get_interface_id (klass))) { - isinst = TRUE; - } else if (m_class_is_array_special_interface (klass)) { - /* slow path */ - // FIXME push/pop LMF - isinst = mono_jiterp_isinst (obj, klass); // FIXME: do not swallow the error - } else { - isinst = FALSE; - } +EMSCRIPTEN_KEEPALIVE int +mono_jiterp_is_special_interface (MonoClass *klass) +{ + return m_class_is_array_special_interface (klass); +} - if (!isinst) { - if (opcode == MINT_ISINST_INTERFACE) - *destination = NULL; - else - return 0; // bailout - } else { - *destination = obj; - } - return 1; - } - case MINT_CASTCLASS_COMMON: - case MINT_ISINST_COMMON: { - if (obj) { - gboolean isinst = mono_class_has_parent_fast (obj->vtable->klass, klass); - - if (!isinst) { - if (opcode == MINT_ISINST_COMMON) - *destination = NULL; - else - return 0; // bailout - } else { - *destination = obj; - } - } else { - *destination = NULL; - } +EMSCRIPTEN_KEEPALIVE int +mono_jiterp_implements_special_interface ( + MonoObject *obj, MonoVTable *vtable, MonoClass *klass +) { + // If null check fusion is active, vtable->max_interface_id will be 0 + return MONO_VTABLE_IMPLEMENTS_INTERFACE (vtable, m_class_get_interface_id (klass)) || + // For special interfaces we need to do a more complex check to see whether the + // cast to the interface is valid in case obj is an array. + // mono_jiterp_isinst will *not* handle nulls for us, and we don't want + // to waste time running the full isinst machinery on nulls anyway, so nullcheck + (obj && mono_jiterp_isinst (obj, klass)); +} + +EMSCRIPTEN_KEEPALIVE int +mono_jiterp_cast_v2 ( + MonoObject **destination, MonoObject *obj, + MonoClass *klass, MintOpcode opcode +) { + if (!obj) { + *destination = NULL; + return 1; + // FIXME push/pop LMF + } else if (!mono_jiterp_isinst (obj, klass)) { + // FIXME: do not swallow the error + if (opcode == MINT_ISINST) { + *destination = NULL; return 1; - } + } else + return 0; // bailout + } else { + *destination = obj; + return 1; } - - return 0; } EMSCRIPTEN_KEEPALIVE void @@ -1170,6 +1129,11 @@ mono_jiterp_trace_transfer ( #define JITERP_MEMBER_BACKWARD_BRANCH_OFFSETS_COUNT 11 #define JITERP_MEMBER_CLAUSE_DATA_OFFSETS 12 #define JITERP_MEMBER_PARAMS_COUNT 13 +#define JITERP_MEMBER_VTABLE 14 +#define JITERP_MEMBER_VTABLE_KLASS 15 +#define JITERP_MEMBER_CLASS_RANK 16 +#define JITERP_MEMBER_CLASS_ELEMENT_CLASS 17 +#define JITERP_MEMBER_BOXED_VALUE_DATA 18 // we use these helpers at JIT time to figure out where to do memory loads and stores EMSCRIPTEN_KEEPALIVE size_t @@ -1203,6 +1167,17 @@ mono_jiterp_get_member_offset (int member) { return offsetof (MonoSpanOfVoid, _length); case JITERP_MEMBER_SPAN_DATA: return offsetof (MonoSpanOfVoid, _reference); + case JITERP_MEMBER_VTABLE: + return offsetof (MonoObject, vtable); + case JITERP_MEMBER_VTABLE_KLASS: + return offsetof (MonoVTable, klass); + case JITERP_MEMBER_CLASS_RANK: + return m_class_offsetof_rank(); + case JITERP_MEMBER_CLASS_ELEMENT_CLASS: + return m_class_offsetof_element_class(); + // see mono_object_get_data + case JITERP_MEMBER_BOXED_VALUE_DATA: + return MONO_ABI_SIZEOF (MonoObject); default: g_assert_not_reached(); } diff --git a/src/mono/mono/mini/interp/transform.c b/src/mono/mono/mini/interp/transform.c index da8c564332bfc6..e3f938a108f808 100644 --- a/src/mono/mono/mini/interp/transform.c +++ b/src/mono/mono/mini/interp/transform.c @@ -4930,7 +4930,8 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, arg_locals = (guint32*) g_malloc ((!!signature->hasthis + signature->param_count) * sizeof (guint32)); /* Allocate locals to store inlined method args from stack */ for (int i = signature->param_count - 1; i >= 0; i--) { - local = create_interp_local (td, signature->params [i]); + MonoType *type = td->locals [td->sp [-1].local].type; + local = create_interp_local (td, type); arg_locals [i + !!signature->hasthis] = local; store_local (td, local); } @@ -4940,11 +4941,7 @@ generate_code (TransformData *td, MonoMethod *method, MonoMethodHeader *header, * If this is value type, it is passed by address and not by value. * Valuetype this local gets integer type MINT_TYPE_I. */ - MonoType *type; - if (m_class_is_valuetype (method->klass)) - type = mono_get_int_type (); - else - type = mono_get_object_type (); + MonoType *type = td->locals [td->sp [-1].local].type; local = create_interp_local (td, type); arg_locals [0] = local; store_local (td, local); diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c index 019fc1a576616b..c2e8bd73b0b760 100644 --- a/src/mono/mono/mini/mini-runtime.c +++ b/src/mono/mono/mini/mini-runtime.c @@ -1547,7 +1547,6 @@ mono_resolve_patch_target_ext (MonoMemoryManager *mem_manager, MonoMethod *metho break; case MONO_PATCH_INFO_VTABLE: target = mono_class_vtable_checked (patch_info->data.klass, error); - mono_error_assert_ok (error); break; case MONO_PATCH_INFO_DELEGATE_INFO: { MonoDelegateClassMethodPair *del_tramp = patch_info->data.del_tramp; @@ -4659,6 +4658,7 @@ mini_init (const char *filename) callbacks.get_frame_info = mono_get_frame_info; callbacks.get_cached_class_info = mono_aot_get_cached_class_info; callbacks.get_class_from_name = mono_aot_get_class_from_name; + callbacks.mono_class_set_deferred_type_load_failure_callback = mono_class_set_type_load_failure; if (mono_llvm_only) { callbacks.build_imt_trampoline = mini_llvmonly_get_imt_trampoline; diff --git a/src/mono/mono/utils/options-def.h b/src/mono/mono/utils/options-def.h index 679fe9dbce3025..4217cbf5ba2181 100644 --- a/src/mono/mono/utils/options-def.h +++ b/src/mono/mono/utils/options-def.h @@ -112,6 +112,8 @@ DEFINE_BOOL(jiterpreter_eliminate_null_checks, "jiterpreter-eliminate-null-check DEFINE_BOOL(jiterpreter_backward_branches_enabled, "jiterpreter-backward-branches-enabled", TRUE, "Enable performing backward branches without exiting traces") // Attempt to use WASM v128 opcodes to implement SIMD interpreter opcodes DEFINE_BOOL(jiterpreter_enable_simd, "jiterpreter-simd-enabled", TRUE, "Attempt to use WebAssembly SIMD support") +// Since the zero page is unallocated, loading array/string/span lengths from null ptrs will yield zero +DEFINE_BOOL(jiterpreter_zero_page_optimization, "jiterpreter-zero-page-optimization", TRUE, "Exploit the zero page being unallocated to optimize out null checks") // When compiling a jit_call wrapper, bypass sharedvt wrappers if possible by inlining their // logic into the compiled wrapper and calling the target AOTed function with native call convention DEFINE_BOOL(jiterpreter_direct_jit_call, "jiterpreter-direct-jit-calls", TRUE, "Bypass gsharedvt wrappers when compiling JIT call wrappers") 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 251119c4af288e..fa94361682af8b 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 @@ -145,16 +145,20 @@ Copyright (c) .NET Foundation. All rights reserved. - + + + + false <_BlazorWebAssemblyLoadAllGlobalizationData Condition="'$(InvariantGlobalization)' != 'true'">$(BlazorWebAssemblyLoadAllGlobalizationData) <_BlazorWebAssemblyLoadAllGlobalizationData Condition="'$(_BlazorWebAssemblyLoadAllGlobalizationData)' == ''">false - <_BlazorIcuDataFileName Condition="'$(InvariantGlobalization)' != 'true' AND '$(BlazorWebAssemblyLoadAllGlobalizationData)' != 'true'">$(BlazorIcuDataFileName) + <_IsHybridGlobalization Condition="'$(InvariantGlobalization)' != 'true' AND '$(HybridGlobalization)' == 'true'"> + <_BlazorIcuDataFileName Condition="'$(InvariantGlobalization)' != 'true' AND '$(BlazorWebAssemblyLoadAllGlobalizationData)' != 'true' AND '$(HybridGlobalization)' != 'true'">$(BlazorIcuDataFileName) <_LoadCustomIcuData>false <_LoadCustomIcuData Condition="'$(_BlazorIcuDataFileName)' != ''">true @@ -172,7 +176,7 @@ Copyright (c) .NET Foundation. All rights reserved. <_WasmCopyOutputSymbolsToOutputDirectory Condition="'$(_WasmCopyOutputSymbolsToOutputDirectory)'==''">true <_WasmEnableThreads>$(WasmEnableThreads) <_WasmEnableThreads Condition="'$(_WasmEnableThreads)' == ''">false - + <_WasmEnableWebcil>$(WasmEnableWebcil) <_WasmEnableWebcil Condition="'$(TargetFrameworkIdentifier)' != '.NETCoreApp' or '$(_TargetingNET80OrLater)' != 'true'">false <_WasmEnableWebcil Condition="'$(_WasmEnableWebcil)' == ''">true @@ -190,11 +194,15 @@ Copyright (c) .NET Foundation. All rights reserved. <_WasmConfigFileCandidates Include="@(StaticWebAsset)" Condition="'%(SourceType)' == 'Discovered'" /> + <_DotNetJsItem Include="@(ReferenceCopyLocalPaths)" Condition="('%(FileName)' == 'dotnet' or '%(FileName)' == 'dotnet.native') and '%(Extension)' == '.js'" /> + + <_DotNetJsBuildVersion>%(_DotNetJsItem.NuGetPackageVersion) + $(IntermediateOutputPath)webcil - + @@ -328,6 +337,7 @@ Copyright (c) .NET Foundation. All rights reserved. LazyLoadedAssemblies="@(BlazorWebAssemblyLazyLoad)" InvariantGlobalization="$(InvariantGlobalization)" LoadCustomIcuData="$(_LoadCustomIcuData)" + IsHybridGlobalization="$(_IsHybridGlobalization)" LoadAllICUData="$(_BlazorWebAssemblyLoadAllGlobalizationData)" StartupMemoryCache="$(_BlazorWebAssemblyStartupMemoryCache)" Jiterpreter="$(_BlazorWebAssemblyJiterpreter)" @@ -391,7 +401,7 @@ Copyright (c) .NET Foundation. All rights reserved. <_WasmPublishWebCilPath>$(IntermediateOutputPath)webcil\publish - + @@ -401,15 +411,15 @@ Copyright (c) .NET Foundation. All rights reserved. - - @@ -515,6 +525,7 @@ Copyright (c) .NET Foundation. All rights reserved. LazyLoadedAssemblies="@(BlazorWebAssemblyLazyLoad)" InvariantGlobalization="$(InvariantGlobalization)" LoadCustomIcuData="$(_LoadCustomIcuData)" + IsHybridGlobalization="$(_IsHybridGlobalization)" LoadAllICUData="$(_BlazorWebAssemblyLoadAllGlobalizationData)" StartupMemoryCache="$(_BlazorWebAssemblyStartupMemoryCache)" Jiterpreter="$(_BlazorWebAssemblyJiterpreter)" diff --git a/src/mono/sample/iOS-NativeAOT/Program.csproj b/src/mono/sample/iOS-NativeAOT/Program.csproj index aa08743cddbab8..c76b6530d811d3 100644 --- a/src/mono/sample/iOS-NativeAOT/Program.csproj +++ b/src/mono/sample/iOS-NativeAOT/Program.csproj @@ -29,8 +29,8 @@ adhoc false - - + + diff --git a/src/mono/sample/wasm/browser-bench/BenchTask.cs b/src/mono/sample/wasm/browser-bench/BenchTask.cs index d9da4502b2d16c..6a41030e44183c 100644 --- a/src/mono/sample/wasm/browser-bench/BenchTask.cs +++ b/src/mono/sample/wasm/browser-bench/BenchTask.cs @@ -59,15 +59,16 @@ public virtual void RunStep() { } public virtual bool HasRunStepAsync => false; - protected virtual int CalculateSteps(int milliseconds, TimeSpan initTs) + protected virtual int CalculateSteps(int milliseconds, TimeSpan initTs, int initialSamples) { - return (int)(milliseconds * InitialSamples / Math.Max(1.0, initTs.TotalMilliseconds)); + return (int)(milliseconds * initialSamples / Math.Max(1.0, initTs.TotalMilliseconds)); } public async Task RunBatch(BenchTask task, int milliseconds) { DateTime start = DateTime.Now; DateTime end; + int initialSamples = InitialSamples; try { // run one to eliminate possible startup overhead and do GC collection @@ -79,15 +80,35 @@ public async Task RunBatch(BenchTask task, int milliseconds) GC.Collect(); start = DateTime.Now; - for (currentStep = 0; currentStep < InitialSamples; currentStep++) - if (HasRunStepAsync) - await RunStepAsync(); - else - RunStep(); + if (HasRunStepAsync) + await RunStepAsync(); + else + RunStep(); end = DateTime.Now; + // try to limit initial samples to 1s + var oneTs = end - start; + var maxInitMs = 1000; + if (oneTs.TotalMilliseconds > 0 && oneTs.TotalMilliseconds*InitialSamples > maxInitMs) + initialSamples = (int)(maxInitMs/oneTs.TotalMilliseconds); + + if (initialSamples > 1) { + GC.Collect(); + + start = DateTime.Now; + for (currentStep = 0; currentStep < initialSamples; currentStep++) + if (HasRunStepAsync) + await RunStepAsync(); + else + RunStep(); + end = DateTime.Now; + } else { + // we already have the 1st measurement + initialSamples = 1; + } + var initTs = end - start; - int steps = CalculateSteps(milliseconds, initTs); + int steps = CalculateSteps(milliseconds, initTs, initialSamples); start = DateTime.Now; for (currentStep = 0; currentStep < steps; currentStep++) @@ -101,14 +122,14 @@ public async Task RunBatch(BenchTask task, int milliseconds) var ts = end - start; - return new Result { span = ts + initTs, steps = steps + InitialSamples, taskName = task.Name, measurementName = Name }; + return new Result { span = ts + initTs, steps = steps + initialSamples, taskName = task.Name, measurementName = Name }; } catch (Exception ex) { end = DateTime.Now; var ts = end - start; Console.WriteLine(ex); - return new Result { span = ts, steps = currentStep + InitialSamples, taskName = task.Name, measurementName = Name + " " + ex.Message }; + return new Result { span = ts, steps = currentStep + initialSamples, taskName = task.Name, measurementName = Name + " " + ex.Message }; } } } diff --git a/src/mono/sample/wasm/browser-bench/String.cs b/src/mono/sample/wasm/browser-bench/String.cs index 2ac38b481d8e43..c00448632fc16d 100644 --- a/src/mono/sample/wasm/browser-bench/String.cs +++ b/src/mono/sample/wasm/browser-bench/String.cs @@ -76,12 +76,14 @@ public override Task AfterBatch() public class NormalizeMeasurement : StringMeasurement { + protected new int len = 8 * 1024; public override string Name => "Normalize"; public override void RunStep() => str.Normalize(); } public class IsNormalizedMeasurement : StringMeasurement { + protected new int len = 8 * 1024; public override string Name => "IsNormalized"; public override void RunStep() => str.IsNormalized(); } @@ -101,7 +103,8 @@ public override Task BeforeBatch() } public class NormalizeMeasurementASCII : ASCIIStringMeasurement - { + { + protected new int len = 8 * 1024; public override string Name => "Normalize ASCII"; public override void RunStep() => str.Normalize(); } @@ -139,6 +142,8 @@ public class TextInfoToTitleCase : TextInfoMeasurement public abstract class StringsCompare : StringMeasurement { + public override int InitialSamples => 100; + protected string strAsciiSuffix; protected string strAsciiPrefix; protected string needleSameAsStrEnd; diff --git a/src/mono/sample/wasm/browser-bench/WebSocket.cs b/src/mono/sample/wasm/browser-bench/WebSocket.cs index d163537f7c593e..9cc16ee09da319 100644 --- a/src/mono/sample/wasm/browser-bench/WebSocket.cs +++ b/src/mono/sample/wasm/browser-bench/WebSocket.cs @@ -88,7 +88,7 @@ public class PartialSend_1BMeasurement : WebSocketMeasurement public override int InitialSamples => 1000; ArraySegment buffer = new ArraySegment(new byte[1]); - protected override int CalculateSteps(int milliseconds, TimeSpan initTs) + protected override int CalculateSteps(int milliseconds, TimeSpan initTs, int initialSamples) { return 250_000; } @@ -112,7 +112,7 @@ public PartialSend_64KBMeasurement() buffer[i] = (byte)(i & 0xff); } } - protected override int CalculateSteps(int milliseconds, TimeSpan initTs) + protected override int CalculateSteps(int milliseconds, TimeSpan initTs, int initialSamples) { return 3000; } @@ -137,7 +137,7 @@ public PartialSend_1MBMeasurement() buffer[i] = (byte)(i & 0xff); } } - protected override int CalculateSteps(int milliseconds, TimeSpan initTs) + protected override int CalculateSteps(int milliseconds, TimeSpan initTs, int initialSamples) { return 100; } @@ -154,9 +154,9 @@ public class PartialReceive_1BMeasurement : WebSocketReceiveMeasurement { ArraySegment buffer = new ArraySegment(new byte[1]); - protected override int CalculateSteps(int milliseconds, TimeSpan initTs) + protected override int CalculateSteps(int milliseconds, TimeSpan initTs, int initialSamples) { - return MaxLength - InitialSamples - 100; + return MaxLength - initialSamples - 100; } public override void RunStep() @@ -177,7 +177,7 @@ public class PartialReceive_10KBMeasurement : WebSocketReceiveMeasurement public override int InitialSamples => 1; ArraySegment buffer = new ArraySegment(new byte[bufferSize]); - protected override int CalculateSteps(int milliseconds, TimeSpan initTs) + protected override int CalculateSteps(int milliseconds, TimeSpan initTs, int initialSamples) { return 500; } @@ -206,7 +206,7 @@ public class PartialReceive_100KBMeasurement : WebSocketReceiveMeasurement public override int InitialSamples => 1; ArraySegment buffer = new ArraySegment(new byte[bufferSize]); - protected override int CalculateSteps(int milliseconds, TimeSpan initTs) + protected override int CalculateSteps(int milliseconds, TimeSpan initTs, int initialSamples) { return MaxMessages - 1; } diff --git a/src/mono/wasi/Makefile b/src/mono/wasi/Makefile index 2905f09f803c7d..9cd33abfa2f003 100644 --- a/src/mono/wasi/Makefile +++ b/src/mono/wasi/Makefile @@ -104,9 +104,9 @@ submit-tests-helix: run-debugger-tests: rm -f $(TOP)/artifacts/bin/DebuggerTestSuite/x64/Debug/*log; \ if [ ! -z "$(TEST_FILTER)" ]; then \ - $(DOTNET) test $(TOP)/src/mono/wasm/debugger/DebuggerTestSuite $(MSBUILD_ARGS) "-l:trx;LogFileName=DebuggerTestsResults.xml" --results-directory $(TOP)/artifacts/log/$(CONFIG) --filter "Category!=failing&FullyQualifiedName$(TEST_FILTER)" $(TEST_ARGS); \ + $(DOTNET) test $(TOP)/src/mono/wasm/debugger/DebuggerTestSuite $(MSBUILD_ARGS) "-l:trx;LogFileName=DebuggerTestsResults.xml" --results-directory $(TOP)/artifacts/log/$(CONFIG) --filter "category!=failing&FullyQualifiedName$(TEST_FILTER)" $(TEST_ARGS); \ else \ - $(DOTNET) test $(TOP)/src/mono/wasm/debugger/DebuggerTestSuite $(MSBUILD_ARGS) "-l:trx;LogFileName=DebuggerTestsResults.xml" --results-directory $(TOP)/artifacts/log/$(CONFIG) --filter "Category!=failing" $(TEST_ARGS); \ + $(DOTNET) test $(TOP)/src/mono/wasm/debugger/DebuggerTestSuite $(MSBUILD_ARGS) "-l:trx;LogFileName=DebuggerTestsResults.xml" --results-directory $(TOP)/artifacts/log/$(CONFIG) --filter "category!=failing" $(TEST_ARGS); \ fi build-dbg-proxy: diff --git a/src/mono/wasm/Makefile b/src/mono/wasm/Makefile index 0968e482f52f85..263838a0a7abd9 100644 --- a/src/mono/wasm/Makefile +++ b/src/mono/wasm/Makefile @@ -148,9 +148,9 @@ submit-tests-helix: run-debugger-tests: rm -f $(TOP)/artifacts/bin/DebuggerTestSuite/x64/Debug/*log; \ if [ ! -z "$(TEST_FILTER)" ]; then \ - $(DOTNET) test $(TOP)/src/mono/wasm/debugger/DebuggerTestSuite $(MSBUILD_ARGS) "-l:trx;LogFileName=DebuggerTestsResults.xml" --results-directory $(TOP)/artifacts/log/$(CONFIG) --filter "Category!=failing&FullyQualifiedName$(TEST_FILTER)" $(TEST_ARGS); \ + $(DOTNET) test $(TOP)/src/mono/wasm/debugger/DebuggerTestSuite $(MSBUILD_ARGS) "-l:trx;LogFileName=DebuggerTestsResults.xml" --results-directory $(TOP)/artifacts/log/$(CONFIG) --filter "category!=failing&FullyQualifiedName$(TEST_FILTER)" $(TEST_ARGS); \ else \ - $(DOTNET) test $(TOP)/src/mono/wasm/debugger/DebuggerTestSuite $(MSBUILD_ARGS) "-l:trx;LogFileName=DebuggerTestsResults.xml" --results-directory $(TOP)/artifacts/log/$(CONFIG) --filter "Category!=failing" $(TEST_ARGS); \ + $(DOTNET) test $(TOP)/src/mono/wasm/debugger/DebuggerTestSuite $(MSBUILD_ARGS) "-l:trx;LogFileName=DebuggerTestsResults.xml" --results-directory $(TOP)/artifacts/log/$(CONFIG) --filter "category!=failing" $(TEST_ARGS); \ fi build-dbg-proxy: diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs index 665735af572a82..8a021a68f1c370 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/BuildPublishTests.cs @@ -64,6 +64,18 @@ public void DefaultTemplate_NoAOT_WithWorkload(string config) } } + [Theory] + [InlineData("Debug")] + [InlineData("Release")] + public void DefaultTemplate_BuildNative_WithWorkload(string config) + { + string id = $"blz_buildandbuildnative_{config}_{Path.GetRandomFileName()}"; + + CreateBlazorWasmTemplateProject(id); + + BlazorBuild(new BlazorBuildOptions(id, config, NativeFilesType.Relinked), "/p:WasmBuildNative=true"); + } + // Disabling for now - publish folder can have more than one dotnet*hash*js, and not sure // how to pick which one to check, for the test //[Theory] diff --git a/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs b/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs index cda5afe8e6dce7..499e38877458ff 100644 --- a/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs +++ b/src/mono/wasm/Wasm.Build.Tests/BuildTestBase.cs @@ -19,6 +19,8 @@ using Xunit.Abstractions; using Xunit.Sdk; using Microsoft.Playwright; +using System.Runtime.Serialization.Json; +using Microsoft.NET.Sdk.WebAssembly; #nullable enable @@ -714,6 +716,7 @@ void AssertIcuAssets() bool expectCJK = false; bool expectNOCJK = false; bool expectFULL = false; + bool expectHYBRID = false; switch (globalizationMode) { case GlobalizationMode.Invariant: @@ -721,6 +724,9 @@ void AssertIcuAssets() case GlobalizationMode.FullIcu: expectFULL = true; break; + case GlobalizationMode.Hybrid: + expectHYBRID = true; + break; case GlobalizationMode.PredefinedIcu: if (string.IsNullOrEmpty(predefinedIcudt)) throw new ArgumentException("WasmBuildTest is invalid, value for predefinedIcudt is required when GlobalizationMode=PredefinedIcu."); @@ -753,6 +759,7 @@ void AssertIcuAssets() AssertFilesExist(bundleDir, new[] { "icudt_EFIGS.dat" }, expectToExist: expectEFIGS); AssertFilesExist(bundleDir, new[] { "icudt_CJK.dat" }, expectToExist: expectCJK); AssertFilesExist(bundleDir, new[] { "icudt_no_CJK.dat" }, expectToExist: expectNOCJK); + AssertFilesExist(bundleDir, new[] { "icudt_hybrid.dat" }, expectToExist: expectHYBRID); } } @@ -822,7 +829,7 @@ protected static void AssertFile(string file0, string file1, string? label = nul return result; } - protected void AssertBlazorBundle(string config, bool isPublish, bool dotnetWasmFromRuntimePack, string targetFramework = DefaultTargetFrameworkForBlazor, string? binFrameworkDir = null) + protected void AssertBlazorBundle(string config, bool isPublish, bool dotnetWasmFromRuntimePack, string targetFramework = DefaultTargetFrameworkForBlazor, string? binFrameworkDir = null, bool expectFingerprinting = false) { binFrameworkDir ??= FindBlazorBinFrameworkDir(config, isPublish, targetFramework); @@ -839,6 +846,41 @@ protected void AssertBlazorBundle(string config, bool isPublish, bool dotnetWasm dotnetJsPath!, "Expected dotnet.native.js to be same as the runtime pack", same: dotnetWasmFromRuntimePack); + + string bootConfigPath = Path.Combine(binFrameworkDir, "blazor.boot.json"); + Assert.True(File.Exists(bootConfigPath), $"Expected to find '{bootConfigPath}'"); + + using (var bootConfigContent = File.OpenRead(bootConfigPath)) + { + var bootConfig = ParseBootData(bootConfigContent); + var dotnetJsEntries = bootConfig.resources.runtime.Keys.Where(k => k.StartsWith("dotnet.") && k.EndsWith(".js")).ToArray(); + + void AssertFileExists(string fileName) + { + string absolutePath = Path.Combine(binFrameworkDir, fileName); + Assert.True(File.Exists(absolutePath), $"Expected to find '{absolutePath}'"); + } + + string versionHashRegex = @"\d.0.\d?(-[a-z]+(\.\d\.\d+\.\d)?)?\.([a-zA-Z0-9])+"; + Assert.Collection( + dotnetJsEntries.OrderBy(f => f), + item => { Assert.Equal(expectFingerprinting ? $"dotnet\\.{versionHashRegex}\\.js" : "dotnet.js", item); AssertFileExists(item); }, + item => { Assert.Matches($"dotnet\\.native\\.{versionHashRegex}\\.js", item); AssertFileExists(item); }, + item => { Assert.Matches($"dotnet\\.runtime\\.{versionHashRegex}\\.js", item); AssertFileExists(item); } + ); + } + } + + private static BootJsonData ParseBootData(Stream stream) + { + stream.Position = 0; + var serializer = new DataContractJsonSerializer( + typeof(BootJsonData), + new DataContractJsonSerializerSettings { UseSimpleDictionaryFormat = true }); + + var config = (BootJsonData?)serializer.ReadObject(stream); + Assert.NotNull(config); + return config; } protected void AssertBlazorBootJson(string config, bool isPublish, bool isNet7AndBelow, string targetFramework = DefaultTargetFrameworkForBlazor, string? binFrameworkDir = null) @@ -1260,7 +1302,8 @@ public enum GlobalizationMode { Invariant, // no icu FullIcu, // full icu data: icudt.dat is loaded - PredefinedIcu // user set WasmIcuDataFileName value and we are loading that file + PredefinedIcu, // user set WasmIcuDataFileName value and we are loading that file + Hybrid // reduced icu, missing data is provided by platform-native functions (web api for wasm) }; public enum NativeFilesType { FromRuntimePack, Relinked, AOT }; diff --git a/src/mono/wasm/Wasm.Build.Tests/HybridGlobalizationTests.cs b/src/mono/wasm/Wasm.Build.Tests/HybridGlobalizationTests.cs new file mode 100644 index 00000000000000..633e060df0f0a8 --- /dev/null +++ b/src/mono/wasm/Wasm.Build.Tests/HybridGlobalizationTests.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.Collections.Generic; +using System.IO; +using Xunit; +using Xunit.Abstractions; + +#nullable enable + +namespace Wasm.Build.Tests +{ + public class HybridGlobalizationTests : BuildTestBase + { + public HybridGlobalizationTests(ITestOutputHelper output, SharedBuildPerTestClassFixture buildContext) + : base(output, buildContext) + { + } + + public static IEnumerable HybridGlobalizationTestData(bool aot, RunHost host) + => ConfigWithAOTData(aot) + .WithRunHosts(host) + .UnwrapItemsAsArrays(); + + [Theory] + [MemberData(nameof(HybridGlobalizationTestData), parameters: new object[] { /*aot*/ false, RunHost.All })] + [MemberData(nameof(HybridGlobalizationTestData), parameters: new object[] { /*aot*/ true, RunHost.All })] + public void AOT_HybridGlobalizationTests(BuildArgs buildArgs, RunHost host, string id) + => TestHybridGlobalizationTests(buildArgs, host, id); + + [Theory] + [MemberData(nameof(HybridGlobalizationTestData), parameters: new object[] { /*aot*/ false, RunHost.All })] + public void RelinkingWithoutAOT(BuildArgs buildArgs, RunHost host, string id) + => TestHybridGlobalizationTests(buildArgs, host, id, + extraProperties: "true", + dotnetWasmFromRuntimePack: false); + + private void TestHybridGlobalizationTests(BuildArgs buildArgs, RunHost host, string id, string extraProperties="", bool? dotnetWasmFromRuntimePack=null) + { + string projectName = $"hybrid"; + extraProperties = $"{extraProperties}true"; + + buildArgs = buildArgs with { ProjectName = projectName }; + buildArgs = ExpandBuildArgs(buildArgs, extraProperties); + + if (dotnetWasmFromRuntimePack == null) + dotnetWasmFromRuntimePack = !(buildArgs.AOT || buildArgs.Config == "Release"); + + string programText = File.ReadAllText(Path.Combine(BuildEnvironment.TestAssetsPath, "Wasm.Buid.Tests.Programs", "HybridGlobalization.cs")); + + BuildProject(buildArgs, + id: id, + new BuildProjectOptions( + InitProject: () => File.WriteAllText(Path.Combine(_projectDir!, "Program.cs"), programText), + DotnetWasmFromRuntimePack: dotnetWasmFromRuntimePack, + GlobalizationMode: GlobalizationMode.Hybrid)); + + string output = RunAndTestWasmApp(buildArgs, expectedExitCode: 42, host: host, id: id); + Assert.Contains("HybridGlobalization works, thrown exception as expected", output); + } + } +} 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 1f2f1d2ad7ecfe..0ff15466c29ef6 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Wasm.Build.Tests.csproj +++ b/src/mono/wasm/Wasm.Build.Tests/Wasm.Build.Tests.csproj @@ -33,6 +33,7 @@ + diff --git a/src/mono/wasm/build/WasmApp.targets b/src/mono/wasm/build/WasmApp.targets index 6a5d91ce57c626..30bcdebf875592 100644 --- a/src/mono/wasm/build/WasmApp.targets +++ b/src/mono/wasm/build/WasmApp.targets @@ -326,19 +326,15 @@ + - false <_HasDotnetWasm Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.wasm'">true <_HasDotnetJsWorker Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.worker.js'">true <_HasDotnetJsSymbols Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.js.symbols'">true <_HasDotnetNativeJs Condition="'%(WasmNativeAsset.FileName)%(WasmNativeAsset.Extension)' == 'dotnet.native.js'">true - <_WasmIcuDataFileName Condition="'$(WasmIcuDataFileName)' != '' and Exists('$(WasmIcuDataFileName)')">$(WasmIcuDataFileName) - <_WasmIcuDataFileName Condition="'$(WasmIcuDataFileName)' != '' and !Exists('$(WasmIcuDataFileName)')">$(MicrosoftNetCoreAppRuntimePackRidNativeDir)$(WasmIcuDataFileName) - - - - - <_WasmIcuDataFileName>$(MicrosoftNetCoreAppRuntimePackRidNativeDir)icudt.dat + false + <_WasmIcuDataFileName Condition="'$(HybridGlobalization)' != 'true' and '$(WasmIcuDataFileName)' != '' and Exists('$(WasmIcuDataFileName)')">$(WasmIcuDataFileName) + <_WasmIcuDataFileName Condition="'$(HybridGlobalization)' != 'true' and '$(WasmIcuDataFileName)' != '' and !Exists('$(WasmIcuDataFileName)')">$(MicrosoftNetCoreAppRuntimePackRidNativeDir)$(WasmIcuDataFileName) @@ -355,12 +351,15 @@ - <_IcuAvailableDataFiles Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)icudt_*" /> - - - + <_HybridGlobalizationDataFiles Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)icudt_hybrid.dat"/> + <_IcuAvailableDataFiles Include="$(MicrosoftNetCoreAppRuntimePackRidNativeDir)icudt_*" Exclude="@(_HybridGlobalizationDataFiles)"/> + + + + + await CheckInspectLocalsAtBreakpointSite( "DebuggerTests.AsyncTests.ContinueWithTests", "ContinueWithInstanceUsingThisAsync", 5, "DebuggerTests.AsyncTests.ContinueWithTests.ContinueWithInstanceUsingThisAsync.AnonymousMethod__6_0", "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerTests.AsyncTests.ContinueWithTests:RunAsync'); })", @@ -66,6 +67,7 @@ public async Task AsyncLocalsInContinueWithInstanceUsingThisBlock() => await Che }); [Fact] // NestedContinueWith + [ActiveIssue("https://github.com/dotnet/runtime/issues/86496", typeof(DebuggerTests), nameof(DebuggerTests.WasmMultiThreaded))] public async Task AsyncLocalsInNestedContinueWithStaticBlock() => await CheckInspectLocalsAtBreakpointSite( "DebuggerTests.AsyncTests.ContinueWithTests", "NestedContinueWithStaticAsync", 5, "DebuggerTests.AsyncTests.ContinueWithTests.NestedContinueWithStaticAsync", "window.setTimeout(function() { invoke_static_method('[debugger-test] DebuggerTests.AsyncTests.ContinueWithTests:RunAsync'); })", @@ -140,7 +142,6 @@ await StepAndCheck(StepKind.Resume, source_to_pause, line2, col2, func_to_pause, public async Task InspectLocalsInAsyncVBMethod() { var expression = $"{{ invoke_static_method('[debugger-test-vb] DebuggerTestVB.TestVbScope:Run'); }}"; - await EvaluateAndCheck( "window.setTimeout(function() {" + expression + "; }, 1);", "dotnet://debugger-test-vb.dll/debugger-test-vb.vb", 14, 12, diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs index adb1e04d8a7f83..f251ceb78b2296 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/BreakpointTests.cs @@ -217,6 +217,7 @@ await EvaluateAndCheck( [MemberData(nameof(FalseConditions))] [MemberData(nameof(TrueConditions))] [MemberData(nameof(InvalidConditions))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/86496", typeof(DebuggerTests), nameof(DebuggerTests.WasmMultiThreaded))] public async Task ConditionalBreakpoint2(string function_to_call, string method_to_stop, string condition, bool bp_stop_expected) { Result [] bps = new Result[2]; @@ -699,6 +700,7 @@ public async Task StepThroughOrNonUserCodeAttributeResumeWithBp(bool justMyCodeE [InlineData(true, "Debugger.stepInto", "RunStepThroughWithNonUserCode", "RunStepThroughWithNonUserCode", -1, 8, "RunStepThroughWithNonUserCode", -1, 4)] [InlineData(false, "Debugger.resume", "RunStepThroughWithNonUserCode", "StepThroughWithNonUserCodeUserBp", 927, 8, "RunStepThroughWithNonUserCode", -1, 4)] [InlineData(true, "Debugger.resume", "RunStepThroughWithNonUserCode", "RunStepThroughWithNonUserCode", -1, 8, "RunStepThroughWithNonUserCode", -1, 4)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/86496", typeof(DebuggerTests), nameof(DebuggerTests.WasmMultiThreaded))] public async Task StepThroughOrNonUserCodeAttributeWithUserBp( bool justMyCodeEnabled, string debuggingFunction, string evalFunName, string functionNameCheck1, int line1, int col1, diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs index 1e87f9e60cc0bf..f03f0518e00205 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/GetPropertiesTests.cs @@ -260,6 +260,7 @@ public GetPropertiesTests(ITestOutputHelper testOutput) : base(testOutput) [MemberData(nameof(ClassGetPropertiesTestData), parameters: false)] [MemberData(nameof(StructGetPropertiesTestData), parameters: true)] [MemberData(nameof(StructGetPropertiesTestData), parameters: false)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/86496", typeof(DebuggerTests), nameof(DebuggerTests.WasmMultiThreaded))] public async Task InspectTypeInheritedMembers(string type_name, bool? own_properties, bool? accessors_only, string[] expected_names, Dictionary all_props, bool is_async) => await InspectTypeInheritedMembersInternal(type_name, own_properties, accessors_only, expected_names, all_props, is_async, AutoEvaluate.Unset); diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/SetNextIpTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/SetNextIpTests.cs index f19f5a556a3cf8..d2cafa0886717e 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/SetNextIpTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/SetNextIpTests.cs @@ -113,6 +113,7 @@ await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-test.cs", } [ConditionalFact(nameof(RunningOnChrome))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/86496", typeof(DebuggerTests), nameof(DebuggerTests.WasmMultiThreaded))] public async Task Lambda() { var debugger_test_loc = "dotnet://debugger-test.dll/debugger-async-test.cs"; @@ -159,6 +160,7 @@ await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-async-tes } [ConditionalFact(nameof(RunningOnChrome))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/86496", typeof(DebuggerTests), nameof(DebuggerTests.WasmMultiThreaded))] public async Task Lambda_InvalidLocation() { var debugger_test_loc = "dotnet://debugger-test.dll/debugger-async-test.cs"; @@ -188,6 +190,7 @@ await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-async-tes } [ConditionalFact(nameof(RunningOnChrome))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/86496", typeof(DebuggerTests), nameof(DebuggerTests.WasmMultiThreaded))] public async Task Lambda_ToNestedLambda() { var debugger_test_loc = "dotnet://debugger-test.dll/debugger-async-test.cs"; @@ -206,7 +209,7 @@ public async Task Lambda_ToNestedLambda() await SetNextIPAndCheck(top_frame["scriptId"].Value(), "dotnet://debugger-test.dll/debugger-async-test.cs", 88, 20, "DebuggerTests.AsyncTests.ContinueWithTests.NestedContinueWithInstanceAsync", expected_error: true); - + await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-async-test.cs", 79, 16, "DebuggerTests.AsyncTests.ContinueWithTests.NestedContinueWithInstanceAsync", locals_fn: async (locals) => { @@ -218,6 +221,7 @@ await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-async-tes } [ConditionalFact(nameof(RunningOnChrome))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/86496", typeof(DebuggerTests), nameof(DebuggerTests.WasmMultiThreaded))] public async Task Lambda_ToNestedSingleLineLambda_Invalid() { var debugger_test_loc = "dotnet://debugger-test.dll/debugger-async-test.cs"; @@ -248,6 +252,7 @@ await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-async-tes } [ConditionalFact(nameof(RunningOnChrome))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/86496", typeof(DebuggerTests), nameof(DebuggerTests.WasmMultiThreaded))] public async Task Lambda_ToNestedSingleLineLambda_Valid() { var debugger_test_loc = "dotnet://debugger-test.dll/debugger-async-test.cs"; @@ -271,7 +276,7 @@ await SetNextIPAndCheck(top_frame["scriptId"].Value(), "dotnet://debugge await CheckValueType(locals, "code", "System.Threading.Tasks.TaskStatus", description: "Created"); await CheckValueType(locals, "dt0", "System.DateTime", description: "1/1/0001 12:00:00 AM"); }); - + await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-async-test.cs", 92, 12, "DebuggerTests.AsyncTests.ContinueWithTests.NestedContinueWithInstanceAsync", locals_fn: async (locals) => { diff --git a/src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs b/src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs index e04639e8e420aa..19875081df6d64 100644 --- a/src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs +++ b/src/mono/wasm/debugger/DebuggerTestSuite/SteppingTests.cs @@ -702,8 +702,8 @@ await EvaluateAndCheck( await StepAndCheck(StepKind.Over, "dotnet://debugger-test.dll/debugger-async-step.cs", 15, 12, "MoveNext"); } - // [ConditionalFact(nameof(RunningOnChrome))] - //[ActiveIssue("https://github.com/dotnet/runtime/issues/42421")] + [ConditionalFact(nameof(RunningOnChrome))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/42421")] public async Task StepOutOfAsyncMethod() { string source_file = "dotnet://debugger-test.dll/debugger-async-step.cs"; @@ -865,8 +865,8 @@ await EvaluateAndCheck( method_name); } - // [ConditionalTheory(nameof(RunningOnChrome))] - //[ActiveIssue("https://github.com/dotnet/runtime/issues/73867")] + [ConditionalTheory(nameof(RunningOnChrome))] + [ActiveIssue("https://github.com/dotnet/runtime/issues/73867")] [InlineData(184, 20, 161, 8, "HiddenLinesContainingStartOfAnAsyncBlock")] [InlineData(206, 20, 201, 8, "HiddenLinesAtTheEndOfANestedAsyncBlockWithWithLineDefaultOutsideTheMethod")] [InlineData(224, 20, 220, 8, "HiddenLinesAtTheEndOfANestedAsyncBlockWithWithLineDefaultOutsideTheMethod2")] @@ -885,6 +885,7 @@ await EvaluateAndCheck( [InlineData(153, 20, 155, 16, "HiddenLinesAtTheEndOfANestedAsyncBlockWithNoLinesAtEndOfTheMethod.AnonymousMethod__1")] [InlineData(154, 20, 155, 16, "HiddenLinesAtTheEndOfANestedAsyncBlockWithNoLinesAtEndOfTheMethod.AnonymousMethod__1")] [InlineData(170, 20, 172, 16, "HiddenLinesAtTheEndOfANestedAsyncBlockWithBreakableLineAtEndOfTheMethod.AnonymousMethod__1")] + [ActiveIssue("https://github.com/dotnet/runtime/issues/86496", typeof(DebuggerTests), nameof(DebuggerTests.WasmMultiThreaded))] public async Task BreakpointOnHiddenLineShouldStopAtEarliestNextAvailableLineAsync(int line_bp, int column_bp, int line_pause, int column_pause, string method_name) { await SetBreakpoint("dotnet://debugger-test.dll/debugger-async-test.cs", line_bp, column_bp); @@ -1219,6 +1220,7 @@ await StepAndCheck(StepKind.Into, "dotnet://Newtonsoft.Json.dll/JArray.cs", 350, [ConditionalTheory(nameof(RunningOnChrome))] [InlineData(true)] [InlineData(false)] + [ActiveIssue("https://github.com/dotnet/runtime/issues/86496", typeof(DebuggerTests), nameof(DebuggerTests.WasmMultiThreaded))] public async Task SkipWasmFunctionsAccordinglyJustMyCode(bool justMyCode) { await SetJustMyCode(justMyCode); diff --git a/src/mono/wasm/debugger/Wasm.Debugger.Tests/wasm.helix.targets b/src/mono/wasm/debugger/Wasm.Debugger.Tests/wasm.helix.targets index f51e059372c82e..d9b1b8262e51ae 100644 --- a/src/mono/wasm/debugger/Wasm.Debugger.Tests/wasm.helix.targets +++ b/src/mono/wasm/debugger/Wasm.Debugger.Tests/wasm.helix.targets @@ -27,8 +27,8 @@ $(TestArchiveTestsDir)Wasm.Debugger.Tests.zip $(HelixCommand) $(_DebuggerTestsWorkItemTimeout) - set "TEST_ARGS=--filter FullyQualifiedName~%(Identity)" - export "TEST_ARGS=--filter FullyQualifiedName~%(Identity)" + set "TEST_ARGS=--filter category^^!=failing^&FullyQualifiedName~%(Identity)" + export "TEST_ARGS=--filter category!=failing&FullyQualifiedName~%(Identity)" diff --git a/src/mono/wasm/host/BrowserHost.cs b/src/mono/wasm/host/BrowserHost.cs index a592ca7386fff3..ec39e008d712da 100644 --- a/src/mono/wasm/host/BrowserHost.cs +++ b/src/mono/wasm/host/BrowserHost.cs @@ -72,7 +72,7 @@ private async Task RunAsync(ILoggerFactory loggerFactory, CancellationToken toke runArgsJson.Save(Path.Combine(_args.CommonConfig.AppPath, "runArgs.json")); string[] urls = envVars.TryGetValue("ASPNETCORE_URLS", out string? aspnetUrls) - ? aspnetUrls.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries) + ? aspnetUrls.Split(';', StringSplitOptions.RemoveEmptyEntries) : new string[] { $"http://127.0.0.1:{_args.CommonConfig.HostProperties.WebServerPort}", "https://127.0.0.1:0" }; (ServerURLs serverURLs, IWebHost host) = await StartWebServerAsync(_args.CommonConfig.AppPath, diff --git a/src/mono/wasm/host/Options.cs b/src/mono/wasm/host/Options.cs index 93c22518a6801f..78c22be9382de6 100644 --- a/src/mono/wasm/host/Options.cs +++ b/src/mono/wasm/host/Options.cs @@ -2068,7 +2068,9 @@ public override int Invoke(IEnumerable arguments) command.Options.WriteOptionDescriptions(CommandSet.Out); return 0; } +#pragma warning disable CA1861 // Avoid constant arrays as arguments. Only invoked when --help is passed. return command.Invoke(new[] { "--help" }); +#pragma warning restore CA1861 } private List> GetCommands() diff --git a/src/mono/wasm/runtime/corebindings.c b/src/mono/wasm/runtime/corebindings.c index 1a6494a101cf31..a6d0f39deb39d6 100644 --- a/src/mono/wasm/runtime/corebindings.c +++ b/src/mono/wasm/runtime/corebindings.c @@ -50,8 +50,6 @@ extern int mono_wasm_compare_string(MonoString **culture, const uint16_t* str1, 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 mono_bool mono_wasm_is_normalized(int32_t normalizationForm, MonoString **src, int *is_exception, MonoObject** ex_result); -extern int mono_wasm_normalize_string(int32_t normalizationForm, MonoString **src, uint16_t* dst, int32_t dstLength, int *is_exception, MonoObject** ex_result); void bindings_initialize_internals (void) { @@ -84,6 +82,4 @@ void bindings_initialize_internals (void) mono_add_internal_call ("Interop/JsGlobalization::StartsWith", mono_wasm_starts_with); mono_add_internal_call ("Interop/JsGlobalization::EndsWith", mono_wasm_ends_with); mono_add_internal_call ("Interop/JsGlobalization::IndexOf", mono_wasm_index_of); - mono_add_internal_call ("Interop/JsGlobalization::IsNormalized", mono_wasm_is_normalized); - mono_add_internal_call ("Interop/JsGlobalization::NormalizeString", mono_wasm_normalize_string); } diff --git a/src/mono/wasm/runtime/cwraps.ts b/src/mono/wasm/runtime/cwraps.ts index f18a313504155c..aa27334f0d3809 100644 --- a/src/mono/wasm/runtime/cwraps.ts +++ b/src/mono/wasm/runtime/cwraps.ts @@ -130,6 +130,8 @@ const fn_signatures: SigLine[] = [ [true, "mono_jiterp_get_simd_opcode", "number", ["number", "number"]], [true, "mono_jiterp_get_arg_offset", "number", ["number", "number", "number"]], [true, "mono_jiterp_get_opcode_info", "number", ["number", "number"]], + [true, "mono_wasm_is_zero_page_reserved", "number", []], + [true, "mono_jiterp_is_special_interface", "number", ["number"]], ...legacy_interop_cwraps ]; @@ -255,6 +257,8 @@ export interface t_Cwraps { mono_jiterp_get_simd_opcode(arity: number, index: number): number; mono_jiterp_get_arg_offset(imethod: number, sig: number, index: number): number; mono_jiterp_get_opcode_info(opcode: number, type: number): number; + mono_wasm_is_zero_page_reserved(): number; + mono_jiterp_is_special_interface(klass: number): number; } const wrapped_c_functions: t_Cwraps = {}; diff --git a/src/mono/wasm/runtime/diagnostics/mock/environment.ts b/src/mono/wasm/runtime/diagnostics/mock/environment.ts index d3d4822aacf69f..17dd2b3cbd9d29 100644 --- a/src/mono/wasm/runtime/diagnostics/mock/environment.ts +++ b/src/mono/wasm/runtime/diagnostics/mock/environment.ts @@ -132,7 +132,7 @@ export function createMockEnvironment(): MockEnvironment { postMessageToBrowser, addEventListenerFromBrowser, createPromiseController, - delay: (ms: number) => new Promise(resolve => setTimeout(resolve, ms)), + delay: (ms: number) => new Promise(resolve => globalThis.setTimeout(resolve, ms)), command, reply, expectAdvertise diff --git a/src/mono/wasm/runtime/dotnet.d.ts b/src/mono/wasm/runtime/dotnet.d.ts index 724d2971747b7b..8a0dfc26cf6f87 100644 --- a/src/mono/wasm/runtime/dotnet.d.ts +++ b/src/mono/wasm/runtime/dotnet.d.ts @@ -3,7 +3,7 @@ //! //! This is generated file, see src/mono/wasm/runtime/rollup.config.js -//! This is not considered public API with backward compatibility guarantees. +//! This is not considered public API with backward compatibility guarantees. declare interface NativePointer { __brandNativePointer: "NativePointer"; @@ -346,7 +346,8 @@ declare enum ICUDataMode { Sharded = 0, All = 1, Invariant = 2, - Custom = 3 + Custom = 3, + Hybrid = 4 } declare global { diff --git a/src/mono/wasm/runtime/driver.c b/src/mono/wasm/runtime/driver.c index a640e88c6e0cd5..6e0d65f7e98245 100644 --- a/src/mono/wasm/runtime/driver.c +++ b/src/mono/wasm/runtime/driver.c @@ -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. #include +#include #include #include #include @@ -219,7 +220,7 @@ mono_wasm_assembly_already_added (const char *assembly_name) WasmAssembly *entry = assemblies; while (entry != NULL) { - int entry_name_minus_extn_len = strlen(entry->assembly.name) - 4; + int entry_name_minus_extn_len = strrchr (entry->assembly.name, '.') - entry->assembly.name; if (entry_name_minus_extn_len == strlen(assembly_name) && strncmp (entry->assembly.name, assembly_name, entry_name_minus_extn_len) == 0) return 1; entry = entry->next; @@ -1413,3 +1414,14 @@ EMSCRIPTEN_KEEPALIVE double mono_wasm_get_f64_unaligned (const double *src) { EMSCRIPTEN_KEEPALIVE int32_t mono_wasm_get_i32_unaligned (const int32_t *src) { return *src; } + +EMSCRIPTEN_KEEPALIVE int mono_wasm_is_zero_page_reserved () { + // If the stack is above the first 512 bytes of memory this indicates that it is safe + // to optimize out null checks for operations that also do a bounds check, like string + // and array element loads. (We already know that Emscripten malloc will never allocate + // data at 0.) This is the default behavior for Emscripten release builds and is + // controlled by the emscripten GLOBAL_BASE option (default value 1024). + // clang/llvm may perform this optimization if --low-memory-unused is set. + // https://github.com/emscripten-core/emscripten/issues/19389 + return (emscripten_stack_get_base() > 512) && (emscripten_stack_get_end() > 512); +} diff --git a/src/mono/wasm/runtime/es6/dotnet.es6.lib.js b/src/mono/wasm/runtime/es6/dotnet.es6.lib.js index 9a525a57e24507..3f5fcabf626565 100644 --- a/src/mono/wasm/runtime/es6/dotnet.es6.lib.js +++ b/src/mono/wasm/runtime/es6/dotnet.es6.lib.js @@ -112,10 +112,6 @@ let linked_functions = [ "mono_wasm_starts_with", "mono_wasm_ends_with", "mono_wasm_index_of", - "mono_wasm_is_normalized", - "mono_wasm_normalize_string", - "mono_wasm_to_Unicode", - "mono_wasm_to_ASCII", "icudt68_dat", ]; diff --git a/src/mono/wasm/runtime/exports-linker.ts b/src/mono/wasm/runtime/exports-linker.ts index 63d1e98a8d359a..b56fe3684fcc06 100644 --- a/src/mono/wasm/runtime/exports-linker.ts +++ b/src/mono/wasm/runtime/exports-linker.ts @@ -29,7 +29,6 @@ import { } from "./net6-legacy/method-calls"; 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_is_normalized, mono_wasm_normalize_string } from "./hybrid-globalization/normalization"; // the methods would be visible to EMCC linker // --- keep in sync with dotnet.cjs.lib.js --- @@ -105,8 +104,6 @@ export function export_linker(): any { mono_wasm_starts_with, mono_wasm_ends_with, mono_wasm_index_of, - mono_wasm_is_normalized, - mono_wasm_normalize_string, // threading exports, if threading is enabled ...mono_wasm_threads_exports, diff --git a/src/mono/wasm/runtime/hybrid-globalization/normalization.ts b/src/mono/wasm/runtime/hybrid-globalization/normalization.ts deleted file mode 100644 index 2faf9e0b66a992..00000000000000 --- a/src/mono/wasm/runtime/hybrid-globalization/normalization.ts +++ /dev/null @@ -1,61 +0,0 @@ -// 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, 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 "../invoke-js"; - -const NORMALIZATION_FORM_MAP = [undefined, "NFC", "NFD", undefined, undefined, "NFKC", "NFKD"]; -const ERROR = -1; - -export function mono_wasm_is_normalized(normalizationForm: number, inputStr: MonoStringRef, is_exception: Int32Ptr, ex_address: MonoObjectRef): number { - const inputRoot = mono_wasm_new_external_root(inputStr), - exceptionRoot = mono_wasm_new_external_root(ex_address); - try { - const jsString = monoStringToString(inputRoot); - if (!jsString) - throw new Error("Invalid string was received."); - - const normalization = normalization_to_string(normalizationForm); - const result = jsString.normalize(normalization); - wrap_no_error_root(is_exception, exceptionRoot); - return result === jsString ? 1 : 0; - } - catch (ex) { - wrap_error_root(is_exception, ex, exceptionRoot); - return ERROR; - } finally { - inputRoot.release(); - exceptionRoot.release(); - } -} - -export function mono_wasm_normalize_string(normalizationForm: number, inputStr: MonoStringRef, dstPtr: number, dstLength: number, is_exception: Int32Ptr, ex_address: MonoObjectRef): number { - const inputRoot = mono_wasm_new_external_root(inputStr), - exceptionRoot = mono_wasm_new_external_root(ex_address); - try { - const jsString = monoStringToString(inputRoot); - if (!jsString) - throw new Error("Invalid string was received."); - - const normalization = normalization_to_string(normalizationForm); - const result = jsString.normalize(normalization); - - // increase the dest buffer - if (result.length > dstLength) - return result.length; - stringToUTF16(dstPtr, dstPtr + 2 * dstLength, result); - return result.length; - } catch (ex) { - wrap_error_root(is_exception, ex, exceptionRoot); - return ERROR; - } finally { - inputRoot.release(); - exceptionRoot.release(); - } -} - -const normalization_to_string = (normalizationForm: number): string => NORMALIZATION_FORM_MAP[normalizationForm] ?? "NFC"; - diff --git a/src/mono/wasm/runtime/jiterpreter-support.ts b/src/mono/wasm/runtime/jiterpreter-support.ts index e0b62832696e9d..65b248573ae3ee 100644 --- a/src/mono/wasm/runtime/jiterpreter-support.ts +++ b/src/mono/wasm/runtime/jiterpreter-support.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 MonoWasmThreads from "consts:monoWasmThreads"; import { NativePointer, ManagedPointer, VoidPtr } from "./types/emscripten"; import { Module, runtimeHelpers } from "./globals"; import { WasmOpcode, WasmSimdOpcode } from "./jiterpreter-opcodes"; @@ -1434,6 +1435,7 @@ export const counters = { failures: 0, bytesGenerated: 0, nullChecksEliminated: 0, + nullChecksFused: 0, backBranchesEmitted: 0, backBranchesNotEmitted: 0, simdFallback: simdFallbackCounters, @@ -1738,6 +1740,11 @@ export const enum JiterpMember { BackwardBranchOffsetsCount = 11, ClauseDataOffsets = 12, ParamsCount = 13, + VTable = 14, + VTableKlass = 15, + ClassRank = 16, + ClassElementClass = 17, + BoxedValueData = 18, } const memberOffsets: { [index: number]: number } = {}; @@ -1777,6 +1784,25 @@ export function bytesFromHex(hex: string): Uint8Array { return bytes; } +export function isZeroPageReserved(): boolean { + // FIXME: This check will always return true on worker threads. + // Right now the jiterpreter is disabled when threading is active, so that's not an issue. + if (MonoWasmThreads) + return false; + + if (!cwraps.mono_wasm_is_zero_page_reserved()) + return false; + + // Determine whether emscripten's stack checker or some other troublemaker has + // written junk at the start of memory. The previous cwraps call will have + // checked whether the stack starts at zero or not (on the main thread). + // We can't do this in the C helper because emcc/asan might be checking pointers. + return (Module.HEAPU32[0] === 0) && + (Module.HEAPU32[1] === 0) && + (Module.HEAPU32[2] === 0) && + (Module.HEAPU32[3] === 0); +} + export type JiterpreterOptions = { enableAll?: boolean; enableTraces: boolean; @@ -1786,6 +1812,7 @@ export type JiterpreterOptions = { enableCallResume: boolean; enableWasmEh: boolean; enableSimd: boolean; + zeroPageOptimization: boolean; // For locations where the jiterpreter heuristic says we will be unable to generate // a trace, insert an entry point opcode anyway. This enables collecting accurate // stats for options like estimateHeat, but raises overhead. @@ -1828,6 +1855,7 @@ const optionNames: { [jsName: string]: string } = { "enableCallResume": "jiterpreter-call-resume-enabled", "enableWasmEh": "jiterpreter-wasm-eh-enabled", "enableSimd": "jiterpreter-simd-enabled", + "zeroPageOptimization": "jiterpreter-zero-page-optimization", "enableStats": "jiterpreter-stats-enabled", "disableHeuristic": "jiterpreter-disable-heuristic", "estimateHeat": "jiterpreter-estimate-heat", diff --git a/src/mono/wasm/runtime/jiterpreter-trace-generator.ts b/src/mono/wasm/runtime/jiterpreter-trace-generator.ts index f4866665ac3614..a8ea1466f5bbb4 100644 --- a/src/mono/wasm/runtime/jiterpreter-trace-generator.ts +++ b/src/mono/wasm/runtime/jiterpreter-trace-generator.ts @@ -22,6 +22,7 @@ import { append_memmove_dest_src, try_append_memset_fast, try_append_memmove_fast, counters, getOpcodeTableValue, getMemberOffset, JiterpMember, BailoutReason, + isZeroPageReserved } from "./jiterpreter-support"; import { compileSimdFeatureDetect } from "./jiterpreter-feature-detect"; import { @@ -151,9 +152,10 @@ function is_backward_branch_target( return false; } -const knownConstantValues = new Map(); +type KnownConstantValue = number | Uint8Array; +const knownConstantValues = new Map(); -function get_known_constant_value(builder: WasmBuilder, localOffset: number): number | undefined { +function get_known_constant_value(builder: WasmBuilder, localOffset: number): KnownConstantValue | undefined { if (isAddressTaken(builder, localOffset)) return undefined; @@ -185,6 +187,10 @@ export function generateWasmBody( builder.cfg.entry(ip); while (ip) { + // This means some code went 'ip = abort; continue' + if (!ip) + break; + builder.cfg.ip = ip; if (ip >= endOfBody) { @@ -598,8 +604,25 @@ export function generateWasmBody( append_ldloc(builder, getArgU16(ip, 3), WasmOpcode.i32_load); // stash it, we'll be using it multiple times builder.local("math_lhs32", WasmOpcode.tee_local); + + /* + const constantIndex = get_known_constant_value(getArgU16(ip, 3)); + if (typeof (constantIndex) === "number") + console.log(`getchr in ${builder.functions[0].name} with constant index ${constantIndex}`); + */ + // str - append_ldloc_cknull(builder, getArgU16(ip, 2), ip, true); + const ptrLocal = builder.options.zeroPageOptimization ? "math_rhs32" : "cknull_ptr"; + if (builder.options.zeroPageOptimization && isZeroPageReserved()) { + // load string ptr and stash it + // if the string ptr is null, the length check will fail and we will bail out, + // so the null check is not necessary + counters.nullChecksFused++; + append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.i32_load); + builder.local(ptrLocal, WasmOpcode.tee_local); + } else + append_ldloc_cknull(builder, getArgU16(ip, 2), ip, true); + // get string length builder.appendU8(WasmOpcode.i32_load); builder.appendMemarg(getMemberOffset(JiterpMember.StringLength), 2); @@ -624,7 +647,7 @@ export function generateWasmBody( builder.local("math_lhs32"); builder.i32_const(2); builder.appendU8(WasmOpcode.i32_mul); - builder.local("cknull_ptr"); + builder.local(ptrLocal); builder.appendU8(WasmOpcode.i32_add); // Load char builder.appendU8(WasmOpcode.i32_load16_u); @@ -824,26 +847,208 @@ export function generateWasmBody( break; } - case MintOpcode.MINT_CASTCLASS: - case MintOpcode.MINT_ISINST: - case MintOpcode.MINT_CASTCLASS_COMMON: - case MintOpcode.MINT_ISINST_COMMON: case MintOpcode.MINT_CASTCLASS_INTERFACE: case MintOpcode.MINT_ISINST_INTERFACE: { - builder.block(); - // dest, src - append_ldloca(builder, getArgU16(ip, 1), 4); - append_ldloca(builder, getArgU16(ip, 2), 0); - // klass - builder.ptr_const(get_imethod_data(frame, getArgU16(ip, 3))); - // opcode - builder.i32_const(opcode); - builder.callImport("cast"); - // if cast operation succeeded, skip the bailout - builder.appendU8(WasmOpcode.br_if); - builder.appendULeb(0); - append_bailout(builder, ip, BailoutReason.CastFailed); - builder.endBlock(); + const klass = get_imethod_data(frame, getArgU16(ip, 3)), + isSpecialInterface = cwraps.mono_jiterp_is_special_interface(klass), + bailoutOnFailure = (opcode === MintOpcode.MINT_CASTCLASS_INTERFACE), + destOffset = getArgU16(ip, 1); + if (!klass) { + record_abort(traceIp, ip, traceName, "null-klass"); + ip = abort; + continue; + } + + builder.block(); // depth x -> 0 (opcode block) + + if (builder.options.zeroPageOptimization && isZeroPageReserved()) { + // Null check fusion is possible, so (obj->vtable) will be 0 for !obj + append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.i32_load); + builder.local("temp_ptr", WasmOpcode.tee_local); + counters.nullChecksFused++; + } else { + builder.block(); // depth 0 -> 1 (null check block) + // src + append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.i32_load); + builder.local("temp_ptr", WasmOpcode.tee_local); + // Null ptr check: If the ptr is non-null, skip this block + builder.appendU8(WasmOpcode.br_if); + builder.appendULeb(0); + builder.local("pLocals"); + builder.i32_const(0); + append_stloc_tail(builder, destOffset, WasmOpcode.i32_store); + // at the end of this block (depth 0) we skip to the end of the opcode block (depth 1) + // because we successfully zeroed the destination register + builder.appendU8(WasmOpcode.br); + builder.appendULeb(1); + builder.endBlock(); // depth 1 -> 0 (end null check block) + // Put ptr back on the stack + builder.local("temp_ptr"); + } + + // the special interface version signature is (obj, vtable, klass), but + // the fast signature is (vtable, klass) + if (isSpecialInterface) { + // load a second copy of obj to build the helper arglist (obj, vtable, klass) + builder.local("temp_ptr"); + } + + builder.appendU8(WasmOpcode.i32_load); // obj->vtable + builder.appendMemarg(getMemberOffset(JiterpMember.VTable), 0); // fixme: alignment + + builder.ptr_const(klass); + builder.callImport(isSpecialInterface ? "imp_iface_s" : "imp_iface"); + + if (bailoutOnFailure) { + // generate a 1 for null ptrs so we don't bail out and instead write the 0 + // to the destination + builder.local("temp_ptr"); + builder.appendU8(WasmOpcode.i32_eqz); + builder.appendU8(WasmOpcode.i32_or); + } + + builder.block(WasmValtype.void, WasmOpcode.if_); // if cast succeeded + builder.local("pLocals"); + builder.local("temp_ptr"); + append_stloc_tail(builder, destOffset, WasmOpcode.i32_store); + builder.appendU8(WasmOpcode.else_); // else cast failed + if (bailoutOnFailure) { + // so bailout + append_bailout(builder, ip, BailoutReason.CastFailed); + } else { + // this is isinst, so write 0 to destination instead + builder.local("pLocals"); + builder.i32_const(0); + append_stloc_tail(builder, destOffset, WasmOpcode.i32_store); + } + builder.endBlock(); // endif + + builder.endBlock(); // depth 0 -> x (end opcode block) + + break; + } + + case MintOpcode.MINT_CASTCLASS_COMMON: + case MintOpcode.MINT_ISINST_COMMON: + case MintOpcode.MINT_CASTCLASS: + case MintOpcode.MINT_ISINST: { + const klass = get_imethod_data(frame, getArgU16(ip, 3)), + canDoFastCheck = (opcode === MintOpcode.MINT_CASTCLASS_COMMON) || + (opcode === MintOpcode.MINT_ISINST_COMMON), + bailoutOnFailure = (opcode === MintOpcode.MINT_CASTCLASS) || + (opcode === MintOpcode.MINT_CASTCLASS_COMMON), + destOffset = getArgU16(ip, 1); + if (!klass) { + record_abort(traceIp, ip, traceName, "null-klass"); + ip = abort; + continue; + } + + builder.block(); // depth x -> 0 (opcode block) + + if (builder.options.zeroPageOptimization && isZeroPageReserved()) { + // Null check fusion is possible, so (obj->vtable)->klass will be 0 for !obj + append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.i32_load); + builder.local("temp_ptr", WasmOpcode.tee_local); + counters.nullChecksFused++; + } else { + builder.block(); // depth 0 -> 1 (null check block) + // src + append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.i32_load); + builder.local("temp_ptr", WasmOpcode.tee_local); + // Null ptr check: If the ptr is non-null, skip this block + builder.appendU8(WasmOpcode.br_if); + builder.appendULeb(0); + builder.local("pLocals"); + builder.i32_const(0); + append_stloc_tail(builder, destOffset, WasmOpcode.i32_store); + // at the end of this block (depth 0) we skip to the end of the opcode block (depth 1) + // because we successfully zeroed the destination register + builder.appendU8(WasmOpcode.br); + builder.appendULeb(1); + builder.endBlock(); // depth 1 -> 0 (end null check block) + // Put ptr back on the stack + builder.local("temp_ptr"); + } + + // If we're here the null check passed and we now need to type-check + builder.appendU8(WasmOpcode.i32_load); // obj->vtable + builder.appendMemarg(getMemberOffset(JiterpMember.VTable), 0); // fixme: alignment + builder.appendU8(WasmOpcode.i32_load); // (obj->vtable)->klass + builder.appendMemarg(getMemberOffset(JiterpMember.VTableKlass), 0); // fixme: alignment + // Stash obj->vtable->klass so we can do a fast has_parent check later + if (canDoFastCheck) + builder.local("temp_ptr2", WasmOpcode.tee_local); + builder.i32_const(klass); + builder.appendU8(WasmOpcode.i32_eq); + builder.block(WasmValtype.void, WasmOpcode.if_); // if A + + // Fast type-check passed (exact match), so store the ptr and continue + builder.local("pLocals"); + builder.local("temp_ptr"); + append_stloc_tail(builder, destOffset, WasmOpcode.i32_store); + + // Fast type-check failed, so call the helper function + builder.appendU8(WasmOpcode.else_); // else A + + if (canDoFastCheck) { + // Fast path for ISINST_COMMON/CASTCLASS_COMMON. We know klass is a simple type + // so all we need to do is a parentage check. + builder.local("temp_ptr2"); // obj->vtable->klass + builder.ptr_const(klass); + builder.callImport("hasparent"); + + if (bailoutOnFailure) { + // generate a 1 for null ptrs so we don't bail out and instead write the 0 + // to the destination + builder.local("temp_ptr"); + builder.appendU8(WasmOpcode.i32_eqz); + builder.appendU8(WasmOpcode.i32_or); + } + + builder.block(WasmValtype.void, WasmOpcode.if_); // if B + // mono_class_has_parent_fast returned 1 so *destination = obj + builder.local("pLocals"); + builder.local("temp_ptr"); + append_stloc_tail(builder, destOffset, WasmOpcode.i32_store); + builder.appendU8(WasmOpcode.else_); // else B + // mono_class_has_parent_fast returned 0 + if (bailoutOnFailure) { + // so bailout + append_bailout(builder, ip, BailoutReason.CastFailed); + } else { + // this is isinst, so write 0 to destination instead + builder.local("pLocals"); + builder.i32_const(0); + append_stloc_tail(builder, destOffset, WasmOpcode.i32_store); + } + builder.endBlock(); // endif B + } else { + // Slow path for ISINST/CASTCLASS, handles things like generics and nullable. + // &dest + append_ldloca(builder, getArgU16(ip, 1), 4); + // src + builder.local("temp_ptr"); + // klass + builder.ptr_const(klass); + // opcode + builder.i32_const(opcode); + builder.callImport("castv2"); + + // We don't need to do an explicit null check because mono_jiterp_cast_v2 does it + + // Check whether the cast operation failed + builder.appendU8(WasmOpcode.i32_eqz); + builder.block(WasmValtype.void, WasmOpcode.if_); // if B + // Cast failed so bail out + append_bailout(builder, ip, BailoutReason.CastFailed); + builder.endBlock(); // endif B + } + + builder.endBlock(); // endif A + + builder.endBlock(); // depth 0 -> x (end opcode block) + break; } @@ -858,19 +1063,70 @@ export function generateWasmBody( builder.callImport("box"); break; } + case MintOpcode.MINT_UNBOX: { - builder.block(); - // MonoClass *c = (MonoClass*)frame->imethod->data_items [ip [3]]; - builder.ptr_const(get_imethod_data(frame, getArgU16(ip, 3))); - // dest, src - append_ldloca(builder, getArgU16(ip, 1), 4); - append_ldloca(builder, getArgU16(ip, 2), 0); - builder.callImport("try_unbox"); - // If the unbox operation succeeded, continue, otherwise bailout - builder.appendU8(WasmOpcode.br_if); - builder.appendULeb(0); + const klass = get_imethod_data(frame, getArgU16(ip, 3)), + // The type check needs to examine the boxed value's rank and element class + elementClassOffset = getMemberOffset(JiterpMember.ClassElementClass), + destOffset = getArgU16(ip, 1), + // Get the class's element class, which is what we will actually type-check against + elementClass = getU32_unaligned(klass + elementClassOffset); + + if (!klass || !elementClass) { + record_abort(traceIp, ip, traceName, "null-klass"); + ip = abort; + continue; + } + + if (builder.options.zeroPageOptimization && isZeroPageReserved()) { + // Null check fusion is possible, so (obj->vtable)->klass will be 0 for !obj + append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.i32_load); + builder.local("temp_ptr", WasmOpcode.tee_local); + counters.nullChecksFused++; + } else { + append_ldloc_cknull(builder, getArgU16(ip, 2), ip, true); + builder.local("temp_ptr", WasmOpcode.tee_local); + } + + // Fetch the object's klass so we can perform a type check + builder.appendU8(WasmOpcode.i32_load); // obj->vtable + builder.appendMemarg(getMemberOffset(JiterpMember.VTable), 0); // fixme: alignment + builder.appendU8(WasmOpcode.i32_load); // (obj->vtable)->klass + builder.appendMemarg(getMemberOffset(JiterpMember.VTableKlass), 0); // fixme: alignment + + // Stash obj->vtable->klass, then check klass->element_class == expected + builder.local("temp_ptr2", WasmOpcode.tee_local); + builder.appendU8(WasmOpcode.i32_load); + builder.appendMemarg(elementClassOffset, 0); + builder.i32_const(elementClass); + builder.appendU8(WasmOpcode.i32_eq); + + // Check klass->rank == 0 + builder.local("temp_ptr2"); + builder.appendU8(WasmOpcode.i32_load8_u); // rank is a uint8 + builder.appendMemarg(getMemberOffset(JiterpMember.ClassRank), 0); + builder.appendU8(WasmOpcode.i32_eqz); + + // (element_class == expected) && (rank == 0) + builder.appendU8(WasmOpcode.i32_and); + + builder.block(WasmValtype.void, WasmOpcode.if_); // if type check passed + + // Type-check passed, so now compute the address of the object's data + // and store the address + builder.local("pLocals"); + builder.local("temp_ptr"); + builder.i32_const(getMemberOffset(JiterpMember.BoxedValueData)); + builder.appendU8(WasmOpcode.i32_add); + append_stloc_tail(builder, destOffset, WasmOpcode.i32_store); + + builder.appendU8(WasmOpcode.else_); // else type check failed + + // append_bailout(builder, ip, BailoutReason.UnboxFailed); - builder.endBlock(); + + builder.endBlock(); // endif A + break; } @@ -1352,8 +1608,11 @@ export function generateWasmBody( ) { if (!emit_simd(builder, ip, opcode, opname, simdIntrinsArgCount, simdIntrinsIndex)) ip = abort; - else + else { containsSimd = true; + // We need to do dreg invalidation differently for simd, especially to handle ldc + skipDregInvalidation = true; + } } else if (opcodeValue === 0) { // This means it was explicitly marked as no-value in the opcode value table // so we can just skip over it. This is done for things like nops. @@ -1472,6 +1731,7 @@ function append_branch_target_block(builder: WasmBuilder, ip: MintOpcodePtr, isB function append_ldloc(builder: WasmBuilder, offset: number, opcodeOrPrefix: WasmOpcode, simdOpcode?: WasmSimdOpcode) { builder.local("pLocals"); + mono_assert(opcodeOrPrefix >= WasmOpcode.i32_load, () => `Expected load opcode but got ${opcodeOrPrefix}`); builder.appendU8(opcodeOrPrefix); if (simdOpcode !== undefined) { // This looks wrong but I assure you it's correct. @@ -1489,6 +1749,7 @@ function append_ldloc(builder: WasmBuilder, offset: number, opcodeOrPrefix: Wasm // The actual store operation is equivalent to `pBase[offset] = value` (alignment has no // observable impact on behavior, other than causing compilation failures if out of range) function append_stloc_tail(builder: WasmBuilder, offset: number, opcodeOrPrefix: WasmOpcode, simdOpcode?: WasmSimdOpcode) { + mono_assert(opcodeOrPrefix >= WasmOpcode.i32_store, () => `Expected store opcode but got ${opcodeOrPrefix}`); builder.appendU8(opcodeOrPrefix); if (simdOpcode !== undefined) { // This looks wrong but I assure you it's correct. @@ -1499,6 +1760,9 @@ function append_stloc_tail(builder: WasmBuilder, offset: number, opcodeOrPrefix: const alignment = (simdOpcode !== undefined) || (opcodeOrPrefix > WasmOpcode.f64_store) ? 0 : 2; builder.appendMemarg(offset, alignment); invalidate_local(offset); + // HACK: Invalidate the second stack slot used by a simd vector + if (simdOpcode !== undefined) + invalidate_local(offset + 8); } // Pass bytesInvalidated=0 if you are reading from the local and the address will never be @@ -1871,8 +2135,10 @@ function emit_fieldop( append_ldloca(builder, localOffset, sizeBytes); // src builder.local("cknull_ptr"); - builder.i32_const(fieldOffset); - builder.appendU8(WasmOpcode.i32_add); + if (fieldOffset !== 0) { + builder.i32_const(fieldOffset); + builder.appendU8(WasmOpcode.i32_add); + } append_memmove_dest_src(builder, sizeBytes); return true; } @@ -1880,8 +2146,10 @@ function emit_fieldop( const klass = get_imethod_data(frame, getArgU16(ip, 4)); // dest = (char*)o + ip [3] builder.local("cknull_ptr"); - builder.i32_const(fieldOffset); - builder.appendU8(WasmOpcode.i32_add); + if (fieldOffset !== 0) { + builder.i32_const(fieldOffset); + builder.appendU8(WasmOpcode.i32_add); + } // src = locals + ip [2] append_ldloca(builder, localOffset, 0); builder.ptr_const(klass); @@ -1892,8 +2160,10 @@ function emit_fieldop( const sizeBytes = getArgU16(ip, 4); // dest builder.local("cknull_ptr"); - builder.i32_const(fieldOffset); - builder.appendU8(WasmOpcode.i32_add); + if (fieldOffset !== 0) { + builder.i32_const(fieldOffset); + builder.appendU8(WasmOpcode.i32_add); + } // src append_ldloca(builder, localOffset, 0); append_memmove_dest_src(builder, sizeBytes); @@ -1905,8 +2175,10 @@ function emit_fieldop( builder.local("pLocals"); // cknull_ptr isn't always initialized here append_ldloc(builder, objectOffset, WasmOpcode.i32_load); - builder.i32_const(fieldOffset); - builder.appendU8(WasmOpcode.i32_add); + if (fieldOffset !== 0) { + builder.i32_const(fieldOffset); + builder.appendU8(WasmOpcode.i32_add); + } append_stloc_tail(builder, localOffset, setter); return true; @@ -2812,18 +3084,35 @@ function append_getelema1( ) { builder.block(); + /* + const constantIndex = get_known_constant_value(indexOffset); + if (typeof (constantIndex) === "number") + console.log(`getelema1 in ${builder.functions[0].name} with constant index ${constantIndex}`); + */ + // load index for check append_ldloc(builder, indexOffset, WasmOpcode.i32_load); // stash it since we need it twice builder.local("math_lhs32", WasmOpcode.tee_local); - // array null check - append_ldloc_cknull(builder, objectOffset, ip, true); + + const ptrLocal = builder.options.zeroPageOptimization ? "math_rhs32" : "cknull_ptr"; + if (builder.options.zeroPageOptimization && isZeroPageReserved()) { + // load array ptr and stash it + // if the array ptr is null, the length check will fail and we will bail out + counters.nullChecksFused++; + append_ldloc(builder, objectOffset, WasmOpcode.i32_load); + builder.local(ptrLocal, WasmOpcode.tee_local); + } else + // array null check + append_ldloc_cknull(builder, objectOffset, ip, true); + // load array length builder.appendU8(WasmOpcode.i32_load); builder.appendMemarg(getMemberOffset(JiterpMember.ArrayLength), 2); // check index < array.length, unsigned. if index is negative it will be interpreted as // a massive value which is naturally going to be bigger than array.length. interp.c // exploits this property so we can too + // for a null array pointer array.length will also be zero thanks to the zero page optimization builder.appendU8(WasmOpcode.i32_lt_u); // bailout unless (index < array.length) builder.appendU8(WasmOpcode.br_if); @@ -2832,7 +3121,7 @@ function append_getelema1( builder.endBlock(); // We did a null check and bounds check so we can now compute the actual address - builder.local("cknull_ptr"); + builder.local(ptrLocal); builder.i32_const(getMemberOffset(JiterpMember.ArrayData)); builder.appendU8(WasmOpcode.i32_add); @@ -2858,6 +3147,7 @@ function emit_arrayop(builder: WasmBuilder, frame: NativePointer, ip: MintOpcode case MintOpcode.MINT_LDLEN: { builder.local("pLocals"); // array null check + // note: zero page optimization is not valid here since we want to throw on null append_ldloc_cknull(builder, objectOffset, ip, true); // load array length builder.appendU8(WasmOpcode.i32_load); @@ -3054,10 +3344,10 @@ function emit_simd( case MintOpcode.MINT_SIMD_V128_LDC: { if (builder.options.enableSimd && getIsWasmSimdSupported()) { builder.local("pLocals"); - builder.v128_const( - localHeapViewU8().slice(ip + 4, ip + 4 + sizeOfV128) - ); + const view = localHeapViewU8().slice(ip + 4, ip + 4 + sizeOfV128); + builder.v128_const(view); append_simd_store(builder, ip); + knownConstantValues.set(getArgU16(ip, 1), view); } else { // dest append_ldloca(builder, getArgU16(ip, 1), sizeOfV128); @@ -3237,11 +3527,34 @@ function emit_simd_3(builder: WasmBuilder, ip: MintOpcodePtr, index: SimdIntrins builder.appendU8(WasmOpcode.i32_eqz); append_stloc_tail(builder, getArgU16(ip, 1), WasmOpcode.i32_store); return true; + case SimdIntrinsic3.V128_I1_SHUFFLE: { + // Detect a constant indices vector and turn it into a const. This allows + // v8 to use a more optimized implementation of the swizzle opcode + const indicesOffset = getArgU16(ip, 3), + constantIndices = get_known_constant_value(builder, indicesOffset); + + // Pre-load destination ptr + builder.local("pLocals"); + // Load vec + append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.PREFIX_simd, WasmSimdOpcode.v128_load); + + if (typeof (constantIndices) === "object") { + // HACK: Use the known constant vector directly instead of loading it from memory. + builder.appendSimd(WasmSimdOpcode.v128_const); + builder.appendBytes(constantIndices); + } else { + // Load the indices from memory + append_ldloc(builder, indicesOffset, WasmOpcode.PREFIX_simd, WasmSimdOpcode.v128_load); + } + + // we now have two vectors on the stack, the values and the byte indices + builder.appendSimd(WasmSimdOpcode.i8x16_swizzle); + append_simd_store(builder, ip); + return true; + } case SimdIntrinsic3.V128_I2_SHUFFLE: case SimdIntrinsic3.V128_I4_SHUFFLE: // FIXME: I8 - // FIXME: Many uses of these shuffles have constant shuffle indices, - // which we could convert into bytes at compile time for vastly improved performance return emit_shuffle(builder, ip, index === SimdIntrinsic3.V128_I2_SHUFFLE ? 8 : 4); default: return false; @@ -3253,41 +3566,60 @@ function emit_simd_3(builder: WasmBuilder, ip: MintOpcodePtr, index: SimdIntrins // implement i16 and i32 shuffles on top of wasm's only shuffle opcode by expanding the // element shuffle indices into byte indices function emit_shuffle(builder: WasmBuilder, ip: MintOpcodePtr, elementCount: number): boolean { - const elementSize = 16 / elementCount; + const elementSize = 16 / elementCount, + indicesOffset = getArgU16(ip, 3), + constantIndices = get_known_constant_value(builder, indicesOffset); mono_assert((elementSize === 2) || (elementSize === 4), "Unsupported shuffle element size"); + + // Pre-load destination ptr builder.local("pLocals"); // Load vec append_ldloc(builder, getArgU16(ip, 2), WasmOpcode.PREFIX_simd, WasmSimdOpcode.v128_load); - // Load indices (in chars) - append_ldloc(builder, getArgU16(ip, 3), WasmOpcode.PREFIX_simd, WasmSimdOpcode.v128_load); - // There's no direct narrowing opcode for i32 -> i8, so we have to do two steps :( - if (elementCount === 4) { - // i32{lane0 ... lane3} -> i16{lane0 ... lane3, 0 ...} + if (typeof (constantIndices) === "object") { + // HACK: We have a known constant shuffle vector with char or int indices. Expand it to + // byte indices and then embed a new constant in the trace. + const newShuffleVector = new Uint8Array(sizeOfV128), + nativeIndices = (elementSize === 2) + ? new Uint16Array(constantIndices.buffer, constantIndices.byteOffset, elementCount) + : new Uint32Array(constantIndices.buffer, constantIndices.byteOffset, elementCount); + for (let i = 0, k = 0; i < elementCount; i++, k += elementSize) { + const elementIndex = nativeIndices[i]; + for (let j = 0; j < elementSize; j++) + newShuffleVector[k + j] = (elementIndex * elementSize) + j; + } + // console.log(`shuffle w/element size ${elementSize} with constant indices ${nativeIndices} (${constantIndices}) -> byte indices ${newShuffleVector}`); + builder.appendSimd(WasmSimdOpcode.v128_const); + builder.appendBytes(newShuffleVector); + } else { + // Load indices (in chars) + append_ldloc(builder, indicesOffset, WasmOpcode.PREFIX_simd, WasmSimdOpcode.v128_load); + // There's no direct narrowing opcode for i32 -> i8, so we have to do two steps :( + if (elementCount === 4) { + // i32{lane0 ... lane3} -> i16{lane0 ... lane3, 0 ...} + builder.v128_const(0); + builder.appendSimd(WasmSimdOpcode.i16x8_narrow_i32x4_u); + } + // Load a zero vector (narrow takes two vectors) builder.v128_const(0); - builder.appendSimd(WasmSimdOpcode.i16x8_narrow_i32x4_u); - } - // Load a zero vector (narrow takes two vectors) - builder.v128_const(0); - // i16{lane0 ... lane7} -> i8{lane0 ... lane7, 0 ...} - builder.appendSimd(WasmSimdOpcode.i8x16_narrow_i16x8_u); - // i8{0, 1, 2, 3 ...} -> i8{0, 0, 1, 1, 2, 2, 3, 3 ...} - builder.appendSimd(WasmSimdOpcode.v128_const); - for (let i = 0; i < elementCount; i++) { - for (let j = 0; j < elementSize; j++) - builder.appendU8(i); - } - builder.appendSimd(WasmSimdOpcode.i8x16_swizzle); - // multiply indices by 2 to scale from char indices to byte indices - builder.i32_const(elementCount === 4 ? 2 : 1); - builder.appendSimd(WasmSimdOpcode.i8x16_shl); - // now add 1 to the secondary lane of each char - builder.appendSimd(WasmSimdOpcode.v128_const); - for (let i = 0; i < elementCount; i++) { - for (let j = 0; j < elementSize; j++) - builder.appendU8(j); + // i16{lane0 ... lane7} -> i8{lane0 ... lane7, 0 ...} + builder.appendSimd(WasmSimdOpcode.i8x16_narrow_i16x8_u); + // i8{0, 1, 2, 3 ...} -> i8{0, 0, 1, 1, 2, 2, 3, 3 ...} + builder.appendSimd(WasmSimdOpcode.v128_const); + for (let i = 0; i < elementCount; i++) { + for (let j = 0; j < elementSize; j++) + builder.appendU8(i); + } + builder.appendSimd(WasmSimdOpcode.i8x16_swizzle); + // multiply indices by 2 to scale from char indices to byte indices + builder.i32_const(elementCount === 4 ? 2 : 1); + builder.appendSimd(WasmSimdOpcode.i8x16_shl); + // now add 1 to the secondary lane of each char + builder.appendSimd(WasmSimdOpcode.v128_const); + for (let i = 0; i < elementCount; i++) { + for (let j = 0; j < elementSize; j++) + builder.appendU8(j); + } } - // we can do a bitwise or since we know we previously multiplied all the lanes by 2 - builder.appendSimd(WasmSimdOpcode.v128_or); // we now have two vectors on the stack, the values and the byte indices builder.appendSimd(WasmSimdOpcode.i8x16_swizzle); append_simd_store(builder, ip); diff --git a/src/mono/wasm/runtime/jiterpreter.ts b/src/mono/wasm/runtime/jiterpreter.ts index caad542eeb668d..ebec1f2caa1eef 100644 --- a/src/mono/wasm/runtime/jiterpreter.ts +++ b/src/mono/wasm/runtime/jiterpreter.ts @@ -10,7 +10,7 @@ import { MintOpcode } from "./mintops"; import cwraps from "./cwraps"; import { MintOpcodePtr, WasmValtype, WasmBuilder, addWasmFunctionPointer, - _now, elapsedTimes, + _now, elapsedTimes, isZeroPageReserved, counters, getRawCwrap, importDef, JiterpreterOptions, getOptions, recordFailure, JiterpMember, getMemberOffset, @@ -263,8 +263,10 @@ function getTraceImports() { importDef("entry", getRawCwrap("mono_jiterp_increase_entry_count")), importDef("value_copy", getRawCwrap("mono_jiterp_value_copy")), importDef("gettype", getRawCwrap("mono_jiterp_gettype_ref")), - importDef("cast", getRawCwrap("mono_jiterp_cast_ref")), - importDef("try_unbox", getRawCwrap("mono_jiterp_try_unbox_ref")), + importDef("castv2", getRawCwrap("mono_jiterp_cast_v2")), + importDef("hasparent", getRawCwrap("mono_jiterp_has_parent_fast")), + importDef("imp_iface", getRawCwrap("mono_jiterp_implements_interface")), + importDef("imp_iface_s", getRawCwrap("mono_jiterp_implements_special_interface")), importDef("box", getRawCwrap("mono_jiterp_box_ref")), importDef("localloc", getRawCwrap("mono_jiterp_localloc")), ["ckovr_i4", "overflow_check_i4", getRawCwrap("mono_jiterp_overflow_check_i4")], @@ -500,7 +502,7 @@ function initialize_builder(builder: WasmBuilder) { WasmValtype.i32, true ); builder.defineType( - "cast", + "castv2", { "destination": WasmValtype.i32, "source": WasmValtype.i32, @@ -510,11 +512,27 @@ function initialize_builder(builder: WasmBuilder) { WasmValtype.i32, true ); builder.defineType( - "try_unbox", + "hasparent", { "klass": WasmValtype.i32, - "destination": WasmValtype.i32, - "source": WasmValtype.i32, + "parent": WasmValtype.i32, + }, + WasmValtype.i32, true + ); + builder.defineType( + "imp_iface", + { + "vtable": WasmValtype.i32, + "klass": WasmValtype.i32, + }, + WasmValtype.i32, true + ); + builder.defineType( + "imp_iface_s", + { + "obj": WasmValtype.i32, + "vtable": WasmValtype.i32, + "klass": WasmValtype.i32, }, WasmValtype.i32, true ); @@ -766,6 +784,7 @@ function generate_wasm( locals: { "disp": WasmValtype.i32, "temp_ptr": WasmValtype.i32, + "temp_ptr2": WasmValtype.i32, "cknull_ptr": WasmValtype.i32, "math_lhs32": WasmValtype.i32, "math_rhs32": WasmValtype.i32, @@ -1034,10 +1053,18 @@ export function jiterpreter_dump_stats(b?: boolean, concise?: boolean) { if (!mostRecentOptions.enableStats && (b !== undefined)) return; - mono_log_info(`// jitted ${counters.bytesGenerated} bytes; ${counters.tracesCompiled} traces (${counters.traceCandidates} candidates, ${(counters.tracesCompiled / counters.traceCandidates * 100).toFixed(1)}%); ${counters.jitCallsCompiled} jit_calls (${(counters.directJitCallsCompiled / counters.jitCallsCompiled * 100).toFixed(1)}% direct); ${counters.entryWrappersCompiled} interp_entries`); - const backBranchHitRate = (counters.backBranchesEmitted / (counters.backBranchesEmitted + counters.backBranchesNotEmitted)) * 100; - const tracesRejected = cwraps.mono_jiterp_get_rejected_trace_count(); - mono_log_info(`// time: ${elapsedTimes.generation | 0}ms generating, ${elapsedTimes.compilation | 0}ms compiling wasm. ${counters.nullChecksEliminated} cknulls removed. ${counters.backBranchesEmitted} back-branches (${counters.backBranchesNotEmitted} failed, ${backBranchHitRate.toFixed(1)}%), ${tracesRejected} traces rejected`); + const backBranchHitRate = (counters.backBranchesEmitted / (counters.backBranchesEmitted + counters.backBranchesNotEmitted)) * 100, + tracesRejected = cwraps.mono_jiterp_get_rejected_trace_count(), + nullChecksEliminatedText = mostRecentOptions.eliminateNullChecks ? counters.nullChecksEliminated.toString() : "off", + nullChecksFusedText = (mostRecentOptions.zeroPageOptimization ? counters.nullChecksFused.toString() + (isZeroPageReserved() ? "" : " (disabled)") : "off"), + backBranchesEmittedText = mostRecentOptions.enableBackwardBranches ? `emitted: ${counters.backBranchesEmitted}, failed: ${counters.backBranchesNotEmitted} (${backBranchHitRate.toFixed(1)}%)` : ": off", + directJitCallsText = counters.jitCallsCompiled ? ( + mostRecentOptions.directJitCalls ? `direct jit calls: ${counters.directJitCallsCompiled} (${(counters.directJitCallsCompiled / counters.jitCallsCompiled * 100).toFixed(1)}%)` : "direct jit calls: off" + ) : ""; + + mono_log_info(`// jitted ${counters.bytesGenerated} bytes; ${counters.tracesCompiled} traces (${(counters.tracesCompiled / counters.traceCandidates * 100).toFixed(1)}%) (${tracesRejected} rejected); ${counters.jitCallsCompiled} jit_calls; ${counters.entryWrappersCompiled} interp_entries`); + mono_log_info(`// cknulls eliminated: ${nullChecksEliminatedText}, fused: ${nullChecksFusedText}; back-branches ${backBranchesEmittedText}; ${directJitCallsText}`); + mono_log_info(`// time: ${elapsedTimes.generation | 0}ms generating, ${elapsedTimes.compilation | 0}ms compiling wasm.`); if (concise) return; diff --git a/src/mono/wasm/runtime/loader/assets.ts b/src/mono/wasm/runtime/loader/assets.ts index 61298966c0fe9f..371bfac0ff024d 100644 --- a/src/mono/wasm/runtime/loader/assets.ts +++ b/src/mono/wasm/runtime/loader/assets.ts @@ -195,7 +195,7 @@ export async function mono_download_assets(): Promise { } export function delay(ms: number): Promise { - return new Promise(resolve => setTimeout(resolve, ms)); + return new Promise(resolve => globalThis.setTimeout(resolve, ms)); } // FIXME: Connection reset is probably the only good one for which we should retry diff --git a/src/mono/wasm/runtime/loader/blazor/_Integration.ts b/src/mono/wasm/runtime/loader/blazor/_Integration.ts index d245991420ae1b..61b2565b736a7b 100644 --- a/src/mono/wasm/runtime/loader/blazor/_Integration.ts +++ b/src/mono/wasm/runtime/loader/blazor/_Integration.ts @@ -203,8 +203,14 @@ function getICUResourceName(bootConfig: BootJsonData, culture: string | undefine } } - const combinedICUResourceName = "icudt.dat"; + if (bootConfig.icuDataMode === ICUDataMode.Hybrid) + { + const reducedICUResourceName = "icudt_hybrid.dat"; + return reducedICUResourceName; + } + if (!culture || bootConfig.icuDataMode === ICUDataMode.All) { + const combinedICUResourceName = "icudt.dat"; return combinedICUResourceName; } diff --git a/src/mono/wasm/runtime/loader/exit.ts b/src/mono/wasm/runtime/loader/exit.ts index 340d99c386b95c..94a6bf8ba7fd80 100644 --- a/src/mono/wasm/runtime/loader/exit.ts +++ b/src/mono/wasm/runtime/loader/exit.ts @@ -140,7 +140,7 @@ function logErrorOnExit(exit_code: number, reason?: any) { mono_log_info_no_prefix("WASM EXIT " + exit_code); } else { - setTimeout(stop_when_ws_buffer_empty, 100); + globalThis.setTimeout(stop_when_ws_buffer_empty, 100); } }; stop_when_ws_buffer_empty(); diff --git a/src/mono/wasm/runtime/net6-legacy/exports-legacy.ts b/src/mono/wasm/runtime/net6-legacy/exports-legacy.ts index a6405c4984ad41..8c1f45f1b9fa4b 100644 --- a/src/mono/wasm/runtime/net6-legacy/exports-legacy.ts +++ b/src/mono/wasm/runtime/net6-legacy/exports-legacy.ts @@ -17,7 +17,7 @@ import { BINDINGType, MONOType } from "./export-types"; import { mono_wasm_load_data_archive } from "../assets"; import { mono_method_resolve } from "./method-binding"; import { runtimeHelpers } from "../globals"; -import { js_string_to_mono_string } from "./strings"; +import { stringToMonoStringIntern, stringToMonoStringUnsafe } from "./strings"; export function export_mono_api(): MONOType { return { @@ -77,6 +77,7 @@ export function cwraps_mono_api(mono: MONOType): void { export function export_internal_api(): any { return { + stringToMonoStringIntern, // MarshalTests.cs mono_method_resolve, //MarshalTests.cs }; } @@ -88,7 +89,7 @@ export function export_binding_api(): BINDINGType { call_assembly_entry_point: mono_call_assembly_entry_point, mono_obj_array_new: null, mono_obj_array_set: null, - js_string_to_mono_string, + js_string_to_mono_string: stringToMonoStringUnsafe, js_typed_array_to_array, mono_array_to_js_array, js_to_mono_obj, diff --git a/src/mono/wasm/runtime/net6-legacy/strings.ts b/src/mono/wasm/runtime/net6-legacy/strings.ts index a6c0790515c0df..ba01a2691de553 100644 --- a/src/mono/wasm/runtime/net6-legacy/strings.ts +++ b/src/mono/wasm/runtime/net6-legacy/strings.ts @@ -3,13 +3,13 @@ import { assert_legacy_interop } from "../pthreads/shared"; import { mono_wasm_new_root } from "../roots"; -import { stringToMonoStringRoot } from "../strings"; -import { MonoString } from "../types/internal"; +import { interned_string_table, mono_wasm_empty_string, stringToInternedMonoStringRoot, stringToMonoStringRoot } from "../strings"; +import { MonoString, is_nullish } from "../types/internal"; /** * @deprecated Not GC or thread safe */ -export function js_string_to_mono_string(string: string): MonoString { +export function stringToMonoStringUnsafe(string: string): MonoString { assert_legacy_interop(); const temp = mono_wasm_new_root(); try { @@ -19,3 +19,20 @@ export function js_string_to_mono_string(string: string): MonoString { temp.release(); } } + +// this is only used in legacy unit tests +export function stringToMonoStringIntern(string: string): string { + if (string.length === 0) + return mono_wasm_empty_string; + + const root = mono_wasm_new_root(); + try { + stringToInternedMonoStringRoot(string, root); + const result = interned_string_table.get(root.value); + mono_assert(!is_nullish(result), "internal error: interned_string_table did not contain string after stringToMonoStringIntern"); + return result; + } + finally { + root.release(); + } +} \ No newline at end of file diff --git a/src/mono/wasm/runtime/rollup.config.js b/src/mono/wasm/runtime/rollup.config.js index a9f04beddde218..b7181da2180b13 100644 --- a/src/mono/wasm/runtime/rollup.config.js +++ b/src/mono/wasm/runtime/rollup.config.js @@ -28,7 +28,7 @@ const terserConfig = { mangle: { // because of stack walk at src/mono/wasm/debugger/BrowserDebugProxy/MonoProxy.cs // and unit test at src\libraries\System.Runtime.InteropServices.JavaScript\tests\System.Runtime.InteropServices.JavaScript.Legacy.UnitTests\timers.mjs - keep_fnames: /(mono_wasm_runtime_ready|mono_wasm_fire_debugger_agent_message_with_data|mono_wasm_fire_debugger_agent_message_with_data_to_pause|mono_wasm_set_timeout_exec)/, + keep_fnames: /(mono_wasm_runtime_ready|mono_wasm_fire_debugger_agent_message_with_data|mono_wasm_fire_debugger_agent_message_with_data_to_pause|mono_wasm_schedule_timer_tick)/, keep_classnames: /(ManagedObject|ManagedError|Span|ArraySegment|WasmRootBuffer|SessionOptionsBuilder)/, }, }; diff --git a/src/mono/wasm/runtime/scheduling.ts b/src/mono/wasm/runtime/scheduling.ts index 85a714ee47442e..7b0755b3148e2b 100644 --- a/src/mono/wasm/runtime/scheduling.ts +++ b/src/mono/wasm/runtime/scheduling.ts @@ -30,15 +30,17 @@ export function prevent_timer_throttling(): void { const light_throttling_frequency = 1000; for (let schedule = next_reach_time; schedule < desired_reach_time; schedule += light_throttling_frequency) { const delay = schedule - now; - setTimeout(() => { - cwraps.mono_wasm_execute_timer(); - pump_count++; - mono_background_exec_until_done(); - }, delay); + globalThis.setTimeout(prevent_timer_throttling_tick, delay); } spread_timers_maximum = desired_reach_time; } +function prevent_timer_throttling_tick() { + cwraps.mono_wasm_execute_timer(); + pump_count++; + mono_background_exec_until_done(); +} + function mono_background_exec_until_done() { while (pump_count > 0) { --pump_count; @@ -48,14 +50,18 @@ function mono_background_exec_until_done() { export function schedule_background_exec(): void { ++pump_count; - setTimeout(mono_background_exec_until_done, 0); + globalThis.setTimeout(mono_background_exec_until_done, 0); } let lastScheduledTimeoutId: any = undefined; export function mono_wasm_schedule_timer(shortestDueTimeMs: number): void { if (lastScheduledTimeoutId) { - clearTimeout(lastScheduledTimeoutId); + globalThis.clearTimeout(lastScheduledTimeoutId); lastScheduledTimeoutId = undefined; } - lastScheduledTimeoutId = setTimeout(cwraps.mono_wasm_execute_timer, shortestDueTimeMs); + lastScheduledTimeoutId = globalThis.setTimeout(mono_wasm_schedule_timer_tick, shortestDueTimeMs); +} + +function mono_wasm_schedule_timer_tick() { + cwraps.mono_wasm_execute_timer(); } diff --git a/src/mono/wasm/runtime/strings.ts b/src/mono/wasm/runtime/strings.ts index ed488d2b70f532..05ffa9717d5261 100644 --- a/src/mono/wasm/runtime/strings.ts +++ b/src/mono/wasm/runtime/strings.ts @@ -170,7 +170,7 @@ export function stringToMonoStringRoot(string: string, result: WasmRoot, internIt: boolean): void { +function storeStringInInternTable(string: string, root: WasmRoot, internIt: boolean): void { if (!root.value) throw new Error("null pointer passed to _store_string_in_intern_table"); @@ -245,7 +245,7 @@ function _store_string_in_intern_table(string: string, root: WasmRoot): void { +function stringToMonoStringNewRoot(string: string, result: WasmRoot): void { const bufferLen = (string.length + 1) * 2; const buffer = Module._malloc(bufferLen); stringToUTF16(buffer as any, buffer as any + bufferLen, string); diff --git a/src/mono/wasm/runtime/types/blazor.ts b/src/mono/wasm/runtime/types/blazor.ts index bf3ec8da02aa04..b0accc82283d49 100644 --- a/src/mono/wasm/runtime/types/blazor.ts +++ b/src/mono/wasm/runtime/types/blazor.ts @@ -44,5 +44,6 @@ export enum ICUDataMode { Sharded = 0, All = 1, Invariant = 2, - Custom = 3 -} \ No newline at end of file + Custom = 3, + Hybrid = 4 +} diff --git a/src/mono/wasm/symbolicator/WasmSymbolicator.cs b/src/mono/wasm/symbolicator/WasmSymbolicator.cs index bb7cb9be9f9454..9ae5547d4d1b42 100644 --- a/src/mono/wasm/symbolicator/WasmSymbolicator.cs +++ b/src/mono/wasm/symbolicator/WasmSymbolicator.cs @@ -47,7 +47,7 @@ public WasmSymbolicator(string? symbolsMapFile, string? symbolPatternsFile, bool int i = 0; foreach (var line in File.ReadAllLines(symbolsMapFile)) { - string[] parts = line.Split(new char[] { ':' }, 2); + string[] parts = line.Split(':', 2); if (parts.Length != 2) { _logger.LogWarning($"Unexpected symbol map format at line {i + 1} in {symbolsMapFile}"); diff --git a/src/mono/wasm/test-main.js b/src/mono/wasm/test-main.js index 79f5620e4b0a6e..1c82380edaf9c1 100644 --- a/src/mono/wasm/test-main.js +++ b/src/mono/wasm/test-main.js @@ -213,7 +213,7 @@ const App = { if ((arguments.length > 2) && (typeof (signature) !== "string")) throw new Error("Invalid number of arguments for call_test_method"); - const fqn = "[System.Runtime.InteropServices.JavaScript.Legacy.UnitTests]System.Runtime.InteropServices.JavaScript.Tests.HelperMarshal:" + method_name; + const fqn = "[System.Runtime.InteropServices.JavaScript.Legacy.Tests]System.Runtime.InteropServices.JavaScript.Tests.HelperMarshal:" + method_name; try { const method = App.runtime.BINDING.bind_static_method(fqn, signature); return method.apply(null, args || []); diff --git a/src/mono/wasm/testassets/Wasm.Buid.Tests.Programs/HybridGlobalization.cs b/src/mono/wasm/testassets/Wasm.Buid.Tests.Programs/HybridGlobalization.cs new file mode 100644 index 00000000000000..094a10d7871790 --- /dev/null +++ b/src/mono/wasm/testassets/Wasm.Buid.Tests.Programs/HybridGlobalization.cs @@ -0,0 +1,25 @@ +using System; +using System.Globalization; + +try +{ + CompareInfo compareInfo = new CultureInfo("es-ES").CompareInfo; + int shouldBeEqual = compareInfo.Compare("A\u0300", "\u00C0", CompareOptions.None); + if (shouldBeEqual != 0) + { + return 1; + } + int shouldThrow = compareInfo.Compare("A\u0300", "\u00C0", CompareOptions.IgnoreNonSpace); + Console.WriteLine($"Did not throw as expected but returned {shouldThrow} as a result. Using CompareOptions.IgnoreNonSpace option alone should be unavailable in HybridGlobalization mode."); +} +catch (PlatformNotSupportedException pnse) +{ + Console.WriteLine($"HybridGlobalization works, thrown exception as expected: {pnse}."); + return 42; +} +catch (Exception ex) +{ + Console.WriteLine($"HybridGlobalization failed, unexpected exception was thrown: {ex}."); + return 2; +} +return 3; diff --git a/src/native/corehost/common.cmake b/src/native/corehost/common.cmake index de14c1e0c853d4..26379c84699eb4 100644 --- a/src/native/corehost/common.cmake +++ b/src/native/corehost/common.cmake @@ -40,8 +40,6 @@ function(set_common_libs TargetType) if((CLR_CMAKE_TARGET_LINUX OR CLR_CMAKE_TARGET_FREEBSD) AND NOT CLR_CMAKE_TARGET_ANDROID) target_link_libraries (${DOTNET_PROJECT_NAME} PRIVATE "pthread") endif() - - target_link_libraries (${DOTNET_PROJECT_NAME} PRIVATE ${CMAKE_DL_LIBS}) endif() if (NOT ${TargetType} STREQUAL "lib-static") @@ -53,5 +51,7 @@ function(set_common_libs TargetType) target_link_libraries(${DOTNET_PROJECT_NAME} PRIVATE atomic.a) endif() endif() + + target_link_libraries (${DOTNET_PROJECT_NAME} PRIVATE ${CMAKE_DL_LIBS}) endif() endfunction() diff --git a/src/native/corehost/hostpolicy/standalone/CMakeLists.txt b/src/native/corehost/hostpolicy/standalone/CMakeLists.txt index 74bea97c58cc17..f977c733d9968c 100644 --- a/src/native/corehost/hostpolicy/standalone/CMakeLists.txt +++ b/src/native/corehost/hostpolicy/standalone/CMakeLists.txt @@ -34,3 +34,7 @@ endif(CLR_CMAKE_HOST_UNIX) install_with_stripped_symbols(hostpolicy TARGETS corehost) target_link_libraries(hostpolicy PRIVATE libhostcommon) + +if((CLR_CMAKE_TARGET_LINUX OR CLR_CMAKE_TARGET_FREEBSD) AND NOT CLR_CMAKE_TARGET_ANDROID) + target_link_libraries (hostpolicy PRIVATE pthread) +endif() diff --git a/src/native/libs/System.Security.Cryptography.Native/configure.cmake b/src/native/libs/System.Security.Cryptography.Native/configure.cmake index e4be90d163454d..74ed49f5d19168 100644 --- a/src/native/libs/System.Security.Cryptography.Native/configure.cmake +++ b/src/native/libs/System.Security.Cryptography.Native/configure.cmake @@ -17,6 +17,11 @@ check_function_exists( HAVE_OPENSSL_CHACHA20POLY1305 ) +check_function_exists( + EVP_sha3_256 + HAVE_OPENSSL_SHA3 +) + 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 590830c2c76e38..d0ae03ef44d828 100644 --- a/src/native/libs/System.Security.Cryptography.Native/entrypoints.c +++ b/src/native/libs/System.Security.Cryptography.Native/entrypoints.c @@ -162,6 +162,9 @@ static const Entry s_cryptoNative[] = DllImportEntry(CryptoNative_EvpSha256) DllImportEntry(CryptoNative_EvpSha384) DllImportEntry(CryptoNative_EvpSha512) + DllImportEntry(CryptoNative_EvpSha3_256) + DllImportEntry(CryptoNative_EvpSha3_384) + DllImportEntry(CryptoNative_EvpSha3_512) DllImportEntry(CryptoNative_ExtendedKeyUsageDestroy) DllImportEntry(CryptoNative_GetAsn1IntegerDerSize) DllImportEntry(CryptoNative_GetAsn1StringBytes) diff --git a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h index e09907c1f8b305..3c8f16f32747f8 100644 --- a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h +++ b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h @@ -153,6 +153,14 @@ const EVP_CIPHER* EVP_chacha20_poly1305(void); #define EVP_CTRL_AEAD_SET_TAG 0x11 #endif +#if !HAVE_OPENSSL_SHA3 +#undef HAVE_OPENSSL_SHA3 +#define HAVE_OPENSSL_SHA3 1 +const EVP_MD *EVP_sha3_256(void); +const EVP_MD *EVP_sha3_384(void); +const EVP_MD *EVP_sha3_512(void); +#endif + #define API_EXISTS(fn) (fn != NULL) // List of all functions from the libssl that are used in the System.Security.Cryptography.Native. @@ -374,6 +382,9 @@ const EVP_CIPHER* EVP_chacha20_poly1305(void); REQUIRED_FUNCTION(EVP_sha256) \ REQUIRED_FUNCTION(EVP_sha384) \ REQUIRED_FUNCTION(EVP_sha512) \ + LIGHTUP_FUNCTION(EVP_sha3_256) \ + LIGHTUP_FUNCTION(EVP_sha3_384) \ + LIGHTUP_FUNCTION(EVP_sha3_512) \ REQUIRED_FUNCTION(EXTENDED_KEY_USAGE_free) \ REQUIRED_FUNCTION(GENERAL_NAMES_free) \ REQUIRED_FUNCTION(HMAC) \ @@ -856,6 +867,9 @@ FOR_ALL_OPENSSL_FUNCTIONS #define EVP_sha256 EVP_sha256_ptr #define EVP_sha384 EVP_sha384_ptr #define EVP_sha512 EVP_sha512_ptr +#define EVP_sha3_256 EVP_sha3_256_ptr +#define EVP_sha3_384 EVP_sha3_384_ptr +#define EVP_sha3_512 EVP_sha3_512_ptr #define EXTENDED_KEY_USAGE_free EXTENDED_KEY_USAGE_free_ptr #define GENERAL_NAMES_free GENERAL_NAMES_free_ptr #define HMAC HMAC_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 6592ac1551a7b8..d7aef5a7d1b674 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 @@ -3,3 +3,4 @@ #cmakedefine01 HAVE_OPENSSL_EC2M #cmakedefine01 HAVE_OPENSSL_ALPN #cmakedefine01 HAVE_OPENSSL_CHACHA20POLY1305 +#cmakedefine01 HAVE_OPENSSL_SHA3 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 f4b6b3e0fc13b2..98da52b81c0cac 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_evp.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp.c @@ -175,6 +175,45 @@ const EVP_MD* CryptoNative_EvpSha512(void) return EVP_sha512(); } +const EVP_MD* CryptoNative_EvpSha3_256(void) +{ + // No error queue impact. +#if HAVE_OPENSSL_SHA3 + if (API_EXISTS(EVP_sha3_256)) + { + return EVP_sha3_256(); + } +#endif + + return NULL; +} + +const EVP_MD* CryptoNative_EvpSha3_384(void) +{ + // No error queue impact. +#if HAVE_OPENSSL_SHA3 + if (API_EXISTS(EVP_sha3_384)) + { + return EVP_sha3_384(); + } +#endif + + return NULL; +} + +const EVP_MD* CryptoNative_EvpSha3_512(void) +{ + // No error queue impact. +#if HAVE_OPENSSL_SHA3 + if (API_EXISTS(EVP_sha3_512)) + { + return EVP_sha3_512(); + } +#endif + + return NULL; +} + int32_t CryptoNative_GetMaxMdSize(void) { // 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 11c8a167191815..1fc90610fe4347 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_evp.h +++ b/src/native/libs/System.Security.Cryptography.Native/pal_evp.h @@ -113,6 +113,30 @@ Direct shim to EVP_sha512. */ PALEXPORT const EVP_MD* CryptoNative_EvpSha512(void); +/* +Function: +EvpSha3_256 + +Direct shim to EVP_sha3_256. +*/ +PALEXPORT const EVP_MD* CryptoNative_EvpSha3_256(void); + +/* +Function: +EvpSha3_384 + +Direct shim to EVP_sha3_384. +*/ +PALEXPORT const EVP_MD* CryptoNative_EvpSha3_384(void); + +/* +Function: +EvpSha3_512 + +Direct shim to EVP_sha3_512. +*/ +PALEXPORT const EVP_MD* CryptoNative_EvpSha3_512(void); + /* Function: GetMaxMdSize diff --git a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs index 553d9dc5a63a3a..93e47600a80cc5 100644 --- a/src/tasks/AotCompilerTask/MonoAOTCompiler.cs +++ b/src/tasks/AotCompilerTask/MonoAOTCompiler.cs @@ -291,6 +291,7 @@ public class MonoAOTCompiler : Microsoft.Build.Utilities.Task private int _totalNumAssemblies; private readonly Dictionary _symbolNameFixups = new(); + private static readonly char[] s_semicolon = new char[]{ ';' }; private bool ProcessAndValidateArguments() { @@ -635,13 +636,13 @@ private PrecompileArguments GetPrecompileArgumentsFor(ITaskItem assemblyItem, st var a = assemblyItem.GetMetadata("AotArguments"); if (a != null) { - aotArgs.AddRange(a.Split(new char[]{ ';' }, StringSplitOptions.RemoveEmptyEntries)); + aotArgs.AddRange(a.Split(s_semicolon, StringSplitOptions.RemoveEmptyEntries)); } var p = assemblyItem.GetMetadata("ProcessArguments"); if (p != null) { - processArgs.AddRange(p.Split(new char[]{ ';' }, StringSplitOptions.RemoveEmptyEntries)); + processArgs.AddRange(p.Split(s_semicolon, StringSplitOptions.RemoveEmptyEntries)); } processArgs.Add("--debug"); diff --git a/src/tasks/AppleAppBuilder/Templates/CMakeLists.txt.template b/src/tasks/AppleAppBuilder/Templates/CMakeLists.txt.template index a95bf1da9a550c..29f0b6eae626ca 100644 --- a/src/tasks/AppleAppBuilder/Templates/CMakeLists.txt.template +++ b/src/tasks/AppleAppBuilder/Templates/CMakeLists.txt.template @@ -82,6 +82,8 @@ target_link_libraries( if(%UseNativeAOTRuntime%) target_link_libraries( %ProjectName% + PRIVATE "-Wl,-u,_NativeAOT_StaticInitialization" + "-Wl,-segprot,__THUNKS,rx,rx" ) endif() \ No newline at end of file diff --git a/src/tasks/Crossgen2Tasks/RunReadyToRunCompiler.cs b/src/tasks/Crossgen2Tasks/RunReadyToRunCompiler.cs index bb12a1bc3c8206..38ca23fedee837 100644 --- a/src/tasks/Crossgen2Tasks/RunReadyToRunCompiler.cs +++ b/src/tasks/Crossgen2Tasks/RunReadyToRunCompiler.cs @@ -346,7 +346,7 @@ private string GenerateCrossgen2ResponseFile() if (!string.IsNullOrEmpty(Crossgen2ExtraCommandLineArgs)) { - foreach (string extraArg in Crossgen2ExtraCommandLineArgs.Split(new char[]{';'}, StringSplitOptions.RemoveEmptyEntries)) + foreach (string extraArg in Crossgen2ExtraCommandLineArgs.Split(';', StringSplitOptions.RemoveEmptyEntries)) { result.AppendLine(extraArg); } 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 282d5cf6d0a580..04068ec8a91142 100644 --- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonData.cs +++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/BootJsonData.cs @@ -144,6 +144,11 @@ public enum ICUDataMode : int /// Load custom icu file provided by the developer. /// Custom = 3, + + /// + /// Use the reduced icudt_hybrid.dat file + /// + Hybrid = 4, } [DataContract] diff --git a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmBuildAssets.cs b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmBuildAssets.cs index d8fe399652dc7a..580f5288b2ccb2 100644 --- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmBuildAssets.cs +++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmBuildAssets.cs @@ -31,6 +31,9 @@ public class ComputeWasmBuildAssets : Task [Required] public ITaskItem[] ProjectSatelliteAssemblies { get; set; } + [Required] + public string DotNetJsVersion { get; set; } + [Required] public string OutputPath { get; set; } @@ -114,7 +117,7 @@ public override bool Execute() if (candidateFileName != "dotnet" || FingerprintDotNetJs) { var itemHash = FileHasher.GetFileHash(candidate.ItemSpec); - newDotnetJSFileName = $"{candidateFileName}.{candidate.GetMetadata("NuGetPackageVersion")}.{itemHash}.js"; + newDotnetJSFileName = $"{candidateFileName}.{DotNetJsVersion}.{itemHash}.js"; var originalFileFullPath = Path.GetFullPath(candidate.ItemSpec); var originalFileDirectory = Path.GetDirectoryName(originalFileFullPath); diff --git a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmPublishAssets.cs b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmPublishAssets.cs index 60c1afd1f02efe..a94c95bc9ddadd 100644 --- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmPublishAssets.cs +++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ComputeWasmPublishAssets.cs @@ -216,7 +216,7 @@ private List ProcessNativeAssets( newDotNetJs = new TaskItem(Path.GetFullPath(aotDotNetJs.ItemSpec), asset.CloneCustomMetadata()); newDotNetJs.SetMetadata("OriginalItemSpec", aotDotNetJs.ItemSpec); - string relativePath = FingerprintDotNetJs + string relativePath = baseName != "dotnet" || FingerprintDotNetJs ? $"_framework/{$"{baseName}.{DotNetJsVersion}.{FileHasher.GetFileHash(aotDotNetJs.ItemSpec)}.js"}" : $"_framework/{baseName}.js"; @@ -242,8 +242,9 @@ private List ProcessNativeAssets( if (isDotNetWasm) { - var aotDotNetWasm = WasmAotAssets.SingleOrDefault(a => { - var name= $"{a.GetMetadata("FileName")}{a.GetMetadata("Extension")}"; + var aotDotNetWasm = WasmAotAssets.SingleOrDefault(a => + { + var name = $"{a.GetMetadata("FileName")}{a.GetMetadata("Extension")}"; return name == "dotnet.native.wasm" || name == "dotnet.wasm"; }); ITaskItem newDotNetWasm = null; @@ -589,7 +590,7 @@ private void GroupResolvedFilesToPublish( } var extension = candidate.GetMetadata("Extension"); - if (string.Equals(extension, ".dll", StringComparison.Ordinal) || string.Equals (extension, Utils.WebcilInWasmExtension, StringComparison.Ordinal)) + if (string.Equals(extension, ".dll", StringComparison.Ordinal) || string.Equals(extension, Utils.WebcilInWasmExtension, StringComparison.Ordinal)) { var culture = candidate.GetMetadata("Culture"); var inferredCulture = candidate.GetMetadata("DestinationSubDirectory").Replace("\\", "/").Trim('/'); 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 413fcdff3da76b..f5d0288ffe4e4f 100644 --- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ConvertDllsToWebCil.cs +++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/ConvertDllsToWebCil.cs @@ -25,6 +25,9 @@ public class ConvertDllsToWebCil : Task [Required] public string OutputPath { get; set; } + [Required] + public string IntermediateOutputPath { get; set; } + [Required] public bool IsEnabled { get; set; } @@ -36,6 +39,7 @@ public class ConvertDllsToWebCil : Task [Output] public string[]? FileWrites => _fileWrites.ToArray(); + public override bool Execute() { var webCilCandidates = new List(); @@ -52,13 +56,17 @@ public override bool Execute() var extension = candidate.GetMetadata("Extension"); var filePath = candidate.ItemSpec; + var webcilFileName = Path.GetFileNameWithoutExtension(filePath) + Utils.WebcilInWasmExtension; if (!Directory.Exists(OutputPath)) Directory.CreateDirectory(OutputPath); if (extension == ".dll") { - var tmpWebcil = Path.GetTempFileName(); + var tmpDir = IntermediateOutputPath; + if (!Directory.Exists(tmpDir)) + Directory.CreateDirectory(tmpDir); + var tmpWebcil = Path.Combine(tmpDir, webcilFileName); var webcilWriter = Microsoft.WebAssembly.Build.Tasks.WebcilConverter.FromPortableExecutable(inputPath: filePath, outputPath: tmpWebcil, logger: Log); webcilWriter.ConvertToWebcil(); @@ -66,7 +74,7 @@ public override bool Execute() if (!Directory.Exists(candicatePath)) Directory.CreateDirectory(candicatePath); - var finalWebcil = Path.Combine(candicatePath, Path.GetFileNameWithoutExtension(filePath) + Utils.WebcilInWasmExtension); + var finalWebcil = Path.Combine(candicatePath, webcilFileName); if (Utils.CopyIfDifferent(tmpWebcil, finalWebcil, useHash: true)) Log.LogMessage(MessageImportance.Low, $"Generated {finalWebcil} ."); else 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 6a21c2886c5b1d..699d34675eee21 100644 --- a/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs +++ b/src/tasks/Microsoft.NET.Sdk.WebAssembly.Pack.Tasks/GenerateWasmBootJson.cs @@ -38,6 +38,8 @@ public class GenerateWasmBootJson : Task public bool LoadAllICUData { get; set; } + public bool IsHybridGlobalization { get; set; } + public bool LoadCustomIcuData { get; set; } public string InvariantGlobalization { get; set; } @@ -83,6 +85,10 @@ public void WriteBootJson(Stream output, string entryAssemblyName) { icuDataMode = ICUDataMode.Invariant; } + else if (IsHybridGlobalization) + { + icuDataMode = ICUDataMode.Hybrid; + } else if (LoadAllICUData) { icuDataMode = ICUDataMode.All; diff --git a/src/tasks/WasmAppBuilder/EmccCompile.cs b/src/tasks/WasmAppBuilder/EmccCompile.cs index aa6d3497d19283..942222ad7cd6ad 100644 --- a/src/tasks/WasmAppBuilder/EmccCompile.cs +++ b/src/tasks/WasmAppBuilder/EmccCompile.cs @@ -42,6 +42,8 @@ public class EmccCompile : Microsoft.Build.Utilities.Task private string? _tempPath; private int _totalFiles; private int _numCompiled; + private static readonly char[] s_semicolon = new char[] { ';' }; + private static readonly char[] s_equalTo = new char[] { '=' }; public override bool Execute() { @@ -90,7 +92,7 @@ private bool ExecuteActual() string depMetadata = srcItem.GetMetadata("Dependencies"); string[] depFiles = string.IsNullOrEmpty(depMetadata) ? Array.Empty() - : depMetadata.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); + : depMetadata.Split(s_semicolon, StringSplitOptions.RemoveEmptyEntries); if (!ShouldCompile(srcFile, objFile, depFiles, out string reason)) { @@ -299,7 +301,7 @@ private Dictionary GetEnvironmentVariablesDict() foreach (var item in EnvironmentVariables) { - var parts = item.ItemSpec.Split(new char[] {'='}, 2, StringSplitOptions.None); + var parts = item.ItemSpec.Split(s_equalTo, 2, StringSplitOptions.None); if (parts.Length == 0) continue; diff --git a/src/tests/Common/XUnitLogChecker/XUnitLogChecker.cs b/src/tests/Common/XUnitLogChecker/XUnitLogChecker.cs index 5fb17cceadb753..82b7d7db602399 100644 --- a/src/tests/Common/XUnitLogChecker/XUnitLogChecker.cs +++ b/src/tests/Common/XUnitLogChecker/XUnitLogChecker.cs @@ -40,9 +40,9 @@ static int Main(string[] args) { if (args.Length < 2) { - Console.WriteLine("[XUnitLogChecker]: The path to the log file and" - + " the name of the wrapper are required for an" - + " accurate check and fixing."); + WriteLineTimestamp("The path to the log file and" + + " the name of the wrapper are required for an" + + " accurate check and fixing."); return MISSING_ARGS; } @@ -64,8 +64,7 @@ static int Main(string[] args) if (File.Exists(finalLogPath)) { - Console.WriteLine($"[XUnitLogChecker]: Item '{wrapperName}' did" - + " complete successfully!"); + WriteLineTimestamp($"Item '{wrapperName}' did complete successfully!"); return SUCCESS; } @@ -80,11 +79,11 @@ static int Main(string[] args) if (!File.Exists(tempLogPath)) { - Console.WriteLine("[XUnitLogChecker]: No logs were found. This work" - + " item was skipped."); - Console.WriteLine($"[XUnitLogChecker]: If this is a mistake, then" - + " something went very wrong. The expected temp" - + $" log name would be: '{tempLogName}'"); + WriteLineTimestamp("No logs were found. This work" + + " item was skipped."); + WriteLineTimestamp($"If this is a mistake, then" + + " something went very wrong. The expected temp" + + $" log name would be: '{tempLogName}'"); return SUCCESS; } @@ -95,8 +94,8 @@ static int Main(string[] args) if (!File.Exists(statsCsvPath)) { - Console.WriteLine("[XUnitLogChecker]: An error occurred. No stats csv" - + $" was found. The expected name would be '{statsCsvPath}'."); + WriteLineTimestamp("An error occurred. No stats csv" + + $" was found. The expected name would be '{statsCsvPath}'."); return FAILURE; } @@ -105,8 +104,8 @@ static int Main(string[] args) if (workItemStats is null) { - Console.WriteLine("[XUnitLogChecker]: Timed out trying to read the" - + $" stats file '{statsCsvPath}'."); + WriteLineTimestamp("Timed out trying to read the" + + $" stats file '{statsCsvPath}'."); return FAILURE; } @@ -128,13 +127,13 @@ static int Main(string[] args) .ToArray(); // Here goes the main core of the XUnit Log Checker :) - Console.WriteLine($"[XUnitLogChecker]: Item '{wrapperName}' did not" - + " finish running. Checking and fixing the log..."); + WriteLineTimestamp($"Item '{wrapperName}' did not" + + " finish running. Checking and fixing the log..."); bool success = FixTheXml(tempLogPath); if (!success) { - Console.WriteLine("[XUnitLogChecker]: Fixing the log failed."); + WriteLineTimestamp("Fixing the log failed."); return FAILURE; } @@ -154,19 +153,22 @@ static int Main(string[] args) } else { - Console.WriteLine("[XUnitLogChecker]: The provided dumps path" - + $" '{dumpsPath}' was not able to be read or" - + " found. Skipping stack traces search..."); + WriteLineTimestamp("The provided dumps path" + + $" '{dumpsPath}' was not able to be read or" + + " found. Skipping stack traces search..."); } } // Rename the temp log to the final log, so that Helix can use it without // knowing what transpired here. File.Move(tempLogPath, finalLogPath); - Console.WriteLine("[XUnitLogChecker]: Finished!"); + WriteLineTimestamp("Finished!"); return SUCCESS; } + static void WriteLineTimestamp(string message) => + Console.WriteLine($"[XUnitLogChecker]: {System.DateTime.Now:HH:mm:ss.ff}: {message}"); + static IEnumerable TryReadFile(string filePath) { // Declaring the enumerable to contain the log lines first because we @@ -187,8 +189,8 @@ static IEnumerable TryReadFile(string filePath) } catch (IOException ioEx) { - Console.WriteLine("[XUnitLogChecker]: Could not read the" - + $" file {filePath}. Retrying..."); + WriteLineTimestamp("Could not read the" + + $" file {filePath}. Retrying..."); // Give it a couple seconds before trying again. Thread.Sleep(2000); @@ -213,8 +215,8 @@ static bool FixTheXml(string xFile) if (logLines is null) { - Console.WriteLine("[XUnitLogChecker]: Timed out trying to read the" - + $" log file '{xFile}'."); + WriteLineTimestamp("Timed out trying to read the" + + $" log file '{xFile}'."); return false; } @@ -303,7 +305,7 @@ static bool FixTheXml(string xFile) if (tags.Count == 0) { - Console.WriteLine($"[XUnitLogChecker]: XUnit log file '{xFile}' was A-OK!"); + WriteLineTimestamp($"XUnit log file '{xFile}' was A-OK!"); return true; } @@ -318,7 +320,7 @@ static bool FixTheXml(string xFile) xsw.WriteLine($""); } - Console.WriteLine("[XUnitLogChecker]: XUnit log file has been fixed!"); + WriteLineTimestamp("XUnit log file has been fixed!"); return true; } @@ -379,7 +381,7 @@ static TagResult[] GetOrderedTagMatches(Match[] openingTags, Match[] closingTags static void PrintStackTracesFromDumps(string dumpsPath, string tempLogPath) { - Console.WriteLine("[XUnitLogChecker]: Checking for dumps..."); + WriteLineTimestamp("Checking for dumps..."); // Read our newly fixed log to retrieve the time and date when the // test was run. This is to exclude potentially existing older dumps @@ -401,7 +403,7 @@ static void PrintStackTracesFromDumps(string dumpsPath, string tempLogPath) if (dumpsFound.Count() == 0) { - Console.WriteLine("[XUnitLogChecker]: No crash dumps found. Continuing..."); + WriteLineTimestamp("No crash dumps found. Continuing..."); return ; } @@ -409,9 +411,9 @@ static void PrintStackTracesFromDumps(string dumpsPath, string tempLogPath) { if (OperatingSystem.IsWindows()) { - Console.WriteLine("[XUnitLogChecker]: Reading crash dump" - + $" '{dumpPath}'..."); - Console.WriteLine("[XUnitLogChecker]: Stack Trace Found:\n"); + WriteLineTimestamp("Reading crash dump" + + $" '{dumpPath}'..."); + WriteLineTimestamp("Stack Trace Found:\n"); CoreclrTestWrapperLib.TryPrintStackTraceFromDmp(dumpPath, Console.Out); @@ -422,14 +424,14 @@ static void PrintStackTracesFromDumps(string dumpsPath, string tempLogPath) if (!File.Exists(crashReportPath)) { - Console.WriteLine("[XUnitLogChecker]: There was no crash" - + $" report for dump '{dumpPath}'. Skipping..."); + WriteLineTimestamp("There was no crash" + + $" report for dump '{dumpPath}'. Skipping..."); continue; } - Console.WriteLine("[XUnitLogChecker]: Reading crash report" - + $" '{crashReportPath}'..."); - Console.WriteLine("[XUnitLogChecker]: Stack Trace Found:\n"); + WriteLineTimestamp("Reading crash report" + + $" '{crashReportPath}'..."); + WriteLineTimestamp("Stack Trace Found:\n"); CoreclrTestWrapperLib.TryPrintStackTraceFromCrashReport(crashReportPath, Console.Out); diff --git a/src/tests/Common/helixpublishwitharcade.proj b/src/tests/Common/helixpublishwitharcade.proj index 13f4894de7c78e..b0ff275f4f591d 100644 --- a/src/tests/Common/helixpublishwitharcade.proj +++ b/src/tests/Common/helixpublishwitharcade.proj @@ -907,7 +907,7 @@ %(PayloadDirectory) $(_WorkaroundForNuGetMigrationsForPrepending) dotnet $(XUnitRunnerDll) %(XUnitWrapperDlls) $(XUnitRunnerArgs) - dotnet $(XUnitRunnerDll) %(XUnitWrapperDlls) $(XUnitRunnerArgs) -trait TestGroup=%(TestGroup) + $(_WorkaroundForNuGetMigrationsForPrepending) dotnet $(XUnitRunnerDll) %(XUnitWrapperDlls) $(XUnitRunnerArgs) -trait TestGroup=%(TestGroup) $([System.TimeSpan]::FromMinutes($(TimeoutPerTestCollectionInMinutes))) coreclr_tests.run.$(TargetOS).$(TargetArchitecture).$(Configuration).mch;coreclr_tests.run.$(TargetOS).$(TargetArchitecture).$(Configuration).log diff --git a/src/tests/Common/test_dependencies/test_dependencies.csproj b/src/tests/Common/test_dependencies/test_dependencies.csproj index 454e4003f0c20f..112944f3544cf2 100644 --- a/src/tests/Common/test_dependencies/test_dependencies.csproj +++ b/src/tests/Common/test_dependencies/test_dependencies.csproj @@ -5,7 +5,7 @@ $(NetCoreAppToolCurrent) true true - win-arm;win-arm64;win-x64;win-x86;$(OutputRID) + win-arm64;win-x64;win-x86;$(OutputRID) true diff --git a/src/tests/Common/test_dependencies_fs/test_dependencies.fsproj b/src/tests/Common/test_dependencies_fs/test_dependencies.fsproj index b7e9dde969981d..02551ebf2ae3e6 100644 --- a/src/tests/Common/test_dependencies_fs/test_dependencies.fsproj +++ b/src/tests/Common/test_dependencies_fs/test_dependencies.fsproj @@ -5,7 +5,7 @@ $(NetCoreAppToolCurrent) true true - win-arm;win-arm64;win-x64;win-x86;$(OutputRID) + win-arm64;win-x64;win-x86;$(OutputRID) true diff --git a/src/tests/Common/testenvironment.proj b/src/tests/Common/testenvironment.proj index 6caa56d38e91bb..4fb1c57a0a1e84 100644 --- a/src/tests/Common/testenvironment.proj +++ b/src/tests/Common/testenvironment.proj @@ -70,6 +70,7 @@ DOTNET_JitRandomEdgeCounts; DOTNET_JitRandomOnStackReplacement; DOTNET_JitRandomlyCollect64BitCounts; + DOTNET_JitGuardedDevirtualizationMaxTypeChecks; DOTNET_TieredPGO_InstrumentedTierAlwaysOptimized; DOTNET_JitForceControlFlowGuard; DOTNET_JitCFGUseDispatcher; @@ -225,7 +226,7 @@ - + diff --git a/src/tests/JIT/HardwareIntrinsics/X86/X86Base/CpuId.cs b/src/tests/JIT/HardwareIntrinsics/X86/X86Base/CpuId.cs index abef01eb32fe14..169b8d8925c9de 100644 --- a/src/tests/JIT/HardwareIntrinsics/X86/X86Base/CpuId.cs +++ b/src/tests/JIT/HardwareIntrinsics/X86/X86Base/CpuId.cs @@ -3,13 +3,15 @@ // using System; +using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Intrinsics.X86; using System.Runtime.Intrinsics; +using System.Reflection; using Xunit; -namespace IntelHardwareIntrinsicTest._CpuId +namespace XarchHardwareIntrinsicTest._CpuId { public class Program { @@ -17,6 +19,7 @@ public class Program const int Fail = 0; [Fact] + [SkipOnMono("Mono does not currently have full support for intrinsics on xarch", TestPlatforms.Any)] public unsafe static void CpuId() { int testResult = Pass; @@ -48,82 +51,88 @@ public unsafe static void CpuId() testResult = Fail; } - int maxFunctionId = eax; + uint maxFunctionId = (uint)eax; - if ((maxFunctionId < 0x00000001) || (Environment.GetEnvironmentVariable("DOTNET_EnableHWIntrinsic") is null)) + if (maxFunctionId < 0x00000001) { Assert.Equal(Pass, testResult); return; } + bool isX86BaseDisabled = !GetDotnetEnable("HWINTRINSIC"); + bool isHierarchyDisabled = isX86BaseDisabled; + (eax, ebx, ecx, edx) = X86Base.CpuId(0x00000001, 0x00000000); - if (IsBitIncorrect(ecx, 28, Avx.IsSupported, "AVX")) + if (IsBitIncorrect(edx, 25, typeof(Sse), Sse.IsSupported, "SSE", ref isHierarchyDisabled)) { - Console.WriteLine("CPUID Fn0000_0001_ECX:AVX != Avx.IsSupported"); testResult = Fail; } - if (IsBitIncorrect(ecx, 25, Aes.IsSupported, "AES")) + if (IsBitIncorrect(edx, 26, typeof(Sse2), Sse2.IsSupported, "SSE2", ref isHierarchyDisabled)) { - Console.WriteLine("CPUID Fn0000_0001_ECX:AES != Aes.IsSupported"); testResult = Fail; } - if (IsBitIncorrect(ecx, 23, Popcnt.IsSupported, "POPCNT")) + bool isSse2HierarchyDisabled = isHierarchyDisabled; + + if (IsBitIncorrect(ecx, 25, typeof(Aes), Aes.IsSupported, "AES", ref isHierarchyDisabled)) { - Console.WriteLine("CPUID Fn0000_0001_ECX:POPCNT != Popcnt.IsSupported"); testResult = Fail; } - if (IsBitIncorrect(ecx, 20, Sse42.IsSupported, "SSE42")) + isHierarchyDisabled = isSse2HierarchyDisabled; + + if (IsBitIncorrect(ecx, 1, typeof(Pclmulqdq), Pclmulqdq.IsSupported, "PCLMULQDQ", ref isHierarchyDisabled)) { - Console.WriteLine("CPUID Fn0000_0001_ECX:SSE42 != Sse42.IsSupported"); testResult = Fail; } - if (IsBitIncorrect(ecx, 19, Sse41.IsSupported, "SSE41")) + isHierarchyDisabled = isSse2HierarchyDisabled | !GetDotnetEnable("SSE3_4"); + + if (IsBitIncorrect(ecx, 0, typeof(Sse3), Sse3.IsSupported, "SSE3", ref isHierarchyDisabled)) { - Console.WriteLine("CPUID Fn0000_0001_ECX:SSE41 != Sse41.IsSupported"); testResult = Fail; } - if (IsBitIncorrect(ecx, 12, Fma.IsSupported, "FMA")) + if (IsBitIncorrect(ecx, 9, typeof(Ssse3), Ssse3.IsSupported, "SSSE3", ref isHierarchyDisabled)) { - Console.WriteLine("CPUID Fn0000_0001_ECX:FMA != Fma.IsSupported"); testResult = Fail; } - if (IsBitIncorrect(ecx, 9, Ssse3.IsSupported, "SSSE3")) + if (IsBitIncorrect(ecx, 19, typeof(Sse41), Sse41.IsSupported, "SSE41", ref isHierarchyDisabled)) { - Console.WriteLine("CPUID Fn0000_0001_ECX:SSSE3 != Ssse3.IsSupported"); testResult = Fail; } - if (IsBitIncorrect(ecx, 1, Pclmulqdq.IsSupported, "PCLMULQDQ")) + if (IsBitIncorrect(ecx, 20, typeof(Sse42), Sse42.IsSupported, "SSE42", ref isHierarchyDisabled)) { - Console.WriteLine("CPUID Fn0000_0001_ECX:PCLMULQDQ != Pclmulqdq.IsSupported"); testResult = Fail; } - if (IsBitIncorrect(ecx, 0, Sse3.IsSupported, "SSE3")) + bool isSse42HierarchyDisabled = isHierarchyDisabled; + + if (IsBitIncorrect(ecx, 23, typeof(Popcnt), Popcnt.IsSupported, "POPCNT", ref isHierarchyDisabled)) { - Console.WriteLine("CPUID Fn0000_0001_ECX:SSE3 != Sse3.IsSupported"); testResult = Fail; } - if (IsBitIncorrect(edx, 26, Sse2.IsSupported, "SSE2")) + isHierarchyDisabled = isSse42HierarchyDisabled; + + if (IsBitIncorrect(ecx, 28, typeof(Avx), Avx.IsSupported, "AVX", ref isHierarchyDisabled)) { - Console.WriteLine("CPUID Fn0000_0001_ECX:SSE2 != Sse2.IsSupported"); testResult = Fail; } - if (IsBitIncorrect(edx, 25, Sse.IsSupported, "SSE")) + bool isAvxHierarchyDisabled = isHierarchyDisabled; + + if (IsBitIncorrect(ecx, 12, typeof(Fma), Fma.IsSupported, "FMA", ref isHierarchyDisabled)) { - Console.WriteLine("CPUID Fn0000_0001_ECX:SSE != Sse.IsSupported"); testResult = Fail; } + bool isFmaHierarchyDisabled = isHierarchyDisabled; + if (maxFunctionId < 0x00000007) { Assert.Equal(Pass, testResult); @@ -132,39 +141,111 @@ public unsafe static void CpuId() (eax, ebx, ecx, edx) = X86Base.CpuId(0x00000007, 0x00000000); - if (IsBitIncorrect(ebx, 8, Bmi2.IsSupported, "BMI2")) + isHierarchyDisabled = isAvxHierarchyDisabled; + + if (IsBitIncorrect(ebx, 5, typeof(Avx2), Avx2.IsSupported, "AVX2", ref isHierarchyDisabled)) { - Console.WriteLine("CPUID Fn0000_0007_EBX:BMI2 != Bmi2.IsSupported"); testResult = Fail; } - if (IsBitIncorrect(ebx, 5, Avx2.IsSupported, "AVX2")) + bool isAvx2HierarchyDisabled = isHierarchyDisabled; + + isHierarchyDisabled = isAvxHierarchyDisabled; + + if (IsBitIncorrect(ebx, 3, typeof(Bmi1), Bmi1.IsSupported, "BMI1", ref isHierarchyDisabled)) { - Console.WriteLine("CPUID Fn0000_0007_EBX:AVX2 != Avx2.IsSupported"); testResult = Fail; } - if (IsBitIncorrect(ebx, 3, Bmi1.IsSupported, "BMI1")) + isHierarchyDisabled = isAvxHierarchyDisabled; + + if (IsBitIncorrect(ebx, 8, typeof(Bmi2), Bmi2.IsSupported, "BMI2", ref isHierarchyDisabled)) { - Console.WriteLine("CPUID Fn0000_0001_EBX:BMI1 != Bmi1.IsSupported"); testResult = Fail; } - (eax, ebx, ecx, edx) = X86Base.CpuId(unchecked((int)0x80000000), 0x00000000); + isHierarchyDisabled = isAvx2HierarchyDisabled | isFmaHierarchyDisabled | OperatingSystem.IsMacOS(); + + for (int i = 0; i < 2; i++) + { + // The runtime currently requires that all of F + BW + CD + DQ + VL be supported together or none + // are supported. To handle this we simple check them all twice so that if any of them are disabled + // the first time around, we'll then assert that they are all actually disabled the second time around + + if (IsBitIncorrect(ebx, 16, typeof(Avx512F), Avx512F.IsSupported, "AVX512F", ref isHierarchyDisabled)) + { + testResult = Fail; + } + + if (IsBitIncorrect(ebx, 31, typeof(Avx512F.VL), Avx512F.VL.IsSupported, "AVX512F_VL", ref isHierarchyDisabled)) + { + testResult = Fail; + } + + if (IsBitIncorrect(ebx, 30, typeof(Avx512BW), Avx512BW.IsSupported, "AVX512BW", ref isHierarchyDisabled)) + { + testResult = Fail; + } + + if (IsBitIncorrect(ebx, 30, typeof(Avx512BW.VL), Avx512BW.VL.IsSupported, "AVX512BW_VL", ref isHierarchyDisabled)) + { + testResult = Fail; + } + + if (IsBitIncorrect(ebx, 28, typeof(Avx512CD), Avx512CD.IsSupported, "AVX512CD", ref isHierarchyDisabled)) + { + testResult = Fail; + } + + if (IsBitIncorrect(ebx, 28, typeof(Avx512CD.VL), Avx512CD.VL.IsSupported, "AVX512CD_VL", ref isHierarchyDisabled)) + { + testResult = Fail; + } + + if (IsBitIncorrect(ebx, 17, typeof(Avx512DQ), Avx512DQ.IsSupported, "AVX512DQ", ref isHierarchyDisabled)) + { + testResult = Fail; + } + + if (IsBitIncorrect(ebx, 17, typeof(Avx512DQ.VL), Avx512DQ.VL.IsSupported, "AVX512DQ_VL", ref isHierarchyDisabled)) + { + testResult = Fail; + } + } + + bool isAvx512HierarchyDisabled = isHierarchyDisabled; + + if (IsBitIncorrect(ecx, 1, typeof(Avx512Vbmi), Avx512Vbmi.IsSupported, "AVX512VBMI", ref isHierarchyDisabled)) + { + testResult = Fail; + } + + if (IsBitIncorrect(ecx, 1, typeof(Avx512Vbmi.VL), Avx512Vbmi.VL.IsSupported, "AVX512VBMI_VL", ref isHierarchyDisabled)) + { + testResult = Fail; + } + + isHierarchyDisabled = isX86BaseDisabled; - if (isAuthenticAmd && ((ebx != 0x68747541) || (ecx != 0x444D4163) || (edx != 0x69746E65))) + if (IsBitIncorrect(edx, 14, typeof(X86Serialize), X86Serialize.IsSupported, "SERIALIZE", ref isHierarchyDisabled)) { - Console.WriteLine("CPUID Fn8000_0000 reported different vendor info from Fn0000_0000"); testResult = Fail; } - if (isGenuineIntel && ((ebx != 0x756E6547) && (ecx != 0x6C65746E) && (edx != 0x6C656E69))) + (eax, ebx, ecx, edx) = X86Base.CpuId(0x00000007, 0x00000001); + + isHierarchyDisabled = isAvx2HierarchyDisabled; + +#pragma warning disable CA2252 // No need to opt into preview feature for an internal test + if (IsBitIncorrect(eax, 4, typeof(AvxVnni), AvxVnni.IsSupported, "AVXVNNI", ref isHierarchyDisabled)) { - Console.WriteLine("CPUID Fn8000_0000 reported different vendor info from Fn0000_0000"); testResult = Fail; } +#pragma warning restore CA2252 + + (eax, ebx, ecx, edx) = X86Base.CpuId(unchecked((int)0x80000000), 0x00000000); - int maxFunctionIdEx = eax; + uint maxFunctionIdEx = (uint)eax; if (maxFunctionIdEx < 0x00000001) { @@ -174,9 +255,63 @@ public unsafe static void CpuId() (eax, ebx, ecx, edx) = X86Base.CpuId(unchecked((int)0x80000001), 0x00000000); - if (IsBitIncorrect(ecx, 5, Lzcnt.IsSupported, "LZCNT")) + isHierarchyDisabled = isX86BaseDisabled; + + if (IsBitIncorrect(ecx, 5, typeof(Lzcnt), Lzcnt.IsSupported, "LZCNT", ref isHierarchyDisabled)) + { + testResult = Fail; + } + + if (IsIncorrect(typeof(Vector64), Vector64.IsHardwareAccelerated, isHierarchyDisabled: true)) + { + testResult = Fail; + } + + if (IsIncorrect(typeof(Vector128), Vector128.IsHardwareAccelerated, isSse2HierarchyDisabled)) + { + testResult = Fail; + } + + if (IsIncorrect(typeof(Vector256), Vector256.IsHardwareAccelerated, isAvx2HierarchyDisabled)) + { + testResult = Fail; + } + + if (IsIncorrect(typeof(Vector512), Vector512.IsHardwareAccelerated, isAvx512HierarchyDisabled)) + { + testResult = Fail; + } + + if (IsIncorrect(typeof(Vector), Vector.IsHardwareAccelerated, isSse2HierarchyDisabled)) { - Console.WriteLine("CPUID Fn8000_0001_ECX:LZCNT != Lzcnt.IsSupported"); + testResult = Fail; + } + + if (Vector.Count == 16) + { + if (!isAvx2HierarchyDisabled) + { + Console.WriteLine($"{typeof(Vector).FullName}.Count returned 16 but the hardware returned 32"); + testResult = Fail; + } + } + else if (Vector.Count == 32) + { + if (isAvx2HierarchyDisabled) + { + Console.WriteLine($"{typeof(Vector).FullName}.Count returned 32 but the hardware returned 16"); + testResult = Fail; + } + } + else + { + Console.WriteLine($"{typeof(Vector).FullName}.Count returned {Vector.Count} which is unexpected"); + testResult = Fail; + } + + if (Vector.Count != (int)typeof(Vector).GetProperty("Count")!.GetValue(null)!) + { + Console.WriteLine($"{typeof(Vector).FullName}.Count returned a different result when called via reflection"); testResult = Fail; } @@ -184,10 +319,84 @@ public unsafe static void CpuId() return; } - static bool IsBitIncorrect(int register, int bitNumber, bool expectedResult, string name) + static bool IsBitIncorrect(int register, int bitNumber, Type isa, bool isSupported, string name, ref bool isHierarchyDisabled) + { + bool isSupportedByHardware = (register & (1 << bitNumber)) != 0; + isHierarchyDisabled |= !GetDotnetEnable(name); + + if (isSupported) + { + if (!isSupportedByHardware) + { + Console.WriteLine($"{isa.FullName}.IsSupported returned true but the hardware returned false"); + return true; + } + + if (isHierarchyDisabled) + { + Console.WriteLine($"{isa.FullName}.IsSupported returned true but the runtime returned false"); + return true; + } + } + else if (isSupportedByHardware) + { + if (!isHierarchyDisabled) + { + Console.WriteLine($"{isa.FullName}.IsSupported returned false but the hardware and runtime returned true"); + return true; + } + } + else + { + // The IsSupported query returned false and the hardware + // says its unsupported, so we're all good + } + + if (isSupported != (bool)isa.GetProperty("IsSupported")!.GetValue(null)!) + { + Console.WriteLine($"{isa.FullName}.IsSupported returned a different result when called via reflection"); + return true; + } + + return false; + } + + static bool IsIncorrect(Type isa, bool isHardwareAccelerated, bool isHierarchyDisabled) { - return ((register & (1 << bitNumber)) != ((expectedResult ? 1 : 0) << bitNumber)) - && (Environment.GetEnvironmentVariable($"DOTNET_Enable{name}") is null); + if (isHardwareAccelerated) + { + if (isHierarchyDisabled) + { + Console.WriteLine($"{isa.FullName}.IsHardwareAccelerated returned true but the runtime returned false"); + return true; + } + } + else if (!isHierarchyDisabled) + { + Console.WriteLine($"{isa.FullName}.IsHardwareAccelerated returned false but the hardware and runtime returned true"); + return true; + } + + if (isHardwareAccelerated != (bool)isa.GetProperty("IsHardwareAccelerated")!.GetValue(null)!) + { + Console.WriteLine($"{isa.FullName}.IsHardwareAccelerated returned a different result when called via reflection"); + return true; + } + + return false; + } + + static bool GetDotnetEnable(string name) + { + string? stringValue = Environment.GetEnvironmentVariable($"DOTNET_Enable{name}"); + + if ((stringValue is null) || !int.TryParse(stringValue, out int value)) + { + // Hardware Intrinsic configuration knobs default to true + return true; + } + + return value != 0; } } } diff --git a/src/tests/JIT/Methodical/structs/systemvbringup/structinregs.csproj b/src/tests/JIT/Methodical/structs/systemvbringup/structinregs.csproj index 211ecef89f561e..d99fc34828d6ad 100644 --- a/src/tests/JIT/Methodical/structs/systemvbringup/structinregs.csproj +++ b/src/tests/JIT/Methodical/structs/systemvbringup/structinregs.csproj @@ -10,6 +10,7 @@ + diff --git a/src/tests/JIT/Methodical/structs/systemvbringup/structpasstest.cs b/src/tests/JIT/Methodical/structs/systemvbringup/structpasstest.cs index 009835efdbdf59..cda27f8b7fca4a 100644 --- a/src/tests/JIT/Methodical/structs/systemvbringup/structpasstest.cs +++ b/src/tests/JIT/Methodical/structs/systemvbringup/structpasstest.cs @@ -35,6 +35,12 @@ public static int TestEntryPoint() { return ret; } + + ret = Program4.Main1(); + if (ret != 100) + { + return ret; + } } catch(Exception e) { diff --git a/src/tests/JIT/Methodical/structs/systemvbringup/structpasstest2.cs b/src/tests/JIT/Methodical/structs/systemvbringup/structpasstest2.cs new file mode 100644 index 00000000000000..9d1073b4df055b --- /dev/null +++ b/src/tests/JIT/Methodical/structs/systemvbringup/structpasstest2.cs @@ -0,0 +1,290 @@ +// 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; + +namespace structinreg +{ + struct Test41 + { + public long l1; + public long l2; + } + + struct Test42 + { + public long l1; + public int i1; + } + + struct Test43 + { + public long l1; + public double d1; + } + + struct Test44 + { + public long l1; + public float f1; + } + + struct Offset1 + { + #pragma warning disable 0169 + long a1; long a2; long a3; long a4; long a5; long a6; long a7; long a8; long a9; long a10; + long a11; long a12; long a13; long a14; long a15; long a16; long a17; long a18; long a19; long a20; + long a21; long a22; long a23; long a24; long a25; long a26; long a27; long a28; long a29; long a30; + long a31; long a32; long a33; long a34; long a35; long a36; long a37; long a38; long a39; long a40; + long a41; long a42; long a43; long a44; long a45; long a46; long a47; long a48; long a49; long a50; + long a51; long a52; long a53; long a54; long a55; long a56; long a57; long a58; long a59; long a60; + long a61; long a62; long a63; long a64; long a65; long a66; long a67; long a68; long a69; long a70; + long a71; long a72; long a73; long a74; long a75; long a76; long a77; long a78; long a79; long a80; + long a81; long a82; long a83; long a84; long a85; long a86; long a87; long a88; long a89; long a90; + long a91; long a92; long a93; long a94; long a95; long a96; long a97; long a98; long a99; long a100; + long a101; long a102; long a103; long a104; long a105; long a106; long a107; long a108; long a109; long a110; + long a111; long a112; long a113; long a114; long a115; long a116; long a117; long a118; long a119; long a120; + long a121; long a122; long a123; long a124; long a125; long a126; long a127; long a128; long a129; long a130; + long a131; long a132; long a133; long a134; long a135; long a136; long a137; long a138; long a139; long a140; + long a141; long a142; long a143; long a144; long a145; long a146; long a147; long a148; long a149; long a150; + long a151; long a152; long a153; long a154; long a155; long a156; long a157; long a158; long a159; long a160; + long a161; long a162; long a163; long a164; long a165; long a166; long a167; long a168; long a169; long a170; + long a171; long a172; long a173; long a174; long a175; long a176; long a177; long a178; long a179; long a180; + long a181; long a182; long a183; long a184; long a185; long a186; long a187; long a188; long a189; long a190; + long a191; long a192; long a193; long a194; long a195; long a196; long a197; long a198; long a199; long a200; + long a201; long a202; long a203; long a204; long a205; long a206; long a207; long a208; long a209; long a210; + long a211; long a212; long a213; long a214; long a215; long a216; long a217; long a218; long a219; long a220; + long a221; long a222; long a223; long a224; long a225; long a226; long a227; long a228; long a229; long a230; + long a231; long a232; long a233; long a234; long a235; long a236; long a237; long a238; long a239; long a240; + long a241; long a242; long a243; long a244; long a245; long a246; + #pragma warning restore 0169 + } + + struct Offset2 + { + #pragma warning disable 0169 + long a1; long a2; long a3; long a4; long a5; long a6; long a7; long a8; long a9; long a10; + long a11; long a12; long a13; long a14; long a15; long a16; long a17; long a18; long a19; long a20; + long a21; long a22; long a23; long a24; long a25; long a26; long a27; long a28; long a29; long a30; + long a31; long a32; long a33; long a34; long a35; long a36; long a37; long a38; long a39; long a40; + long a41; long a42; long a43; long a44; long a45; long a46; long a47; long a48; long a49; long a50; + long a51; long a52; long a53; long a54; long a55; long a56; long a57; long a58; long a59; long a60; + long a61; long a62; long a63; long a64; long a65; long a66; long a67; long a68; long a69; long a70; + long a71; long a72; long a73; long a74; long a75; long a76; long a77; long a78; long a79; long a80; + long a81; long a82; long a83; long a84; long a85; long a86; long a87; long a88; long a89; long a90; + long a91; long a92; long a93; long a94; long a95; long a96; long a97; long a98; long a99; long a100; + long a101; long a102; long a103; long a104; long a105; long a106; long a107; long a108; long a109; long a110; + long a111; long a112; long a113; long a114; long a115; long a116; long a117; long a118; long a119; long a120; + long a121; long a122; long a123; long a124; long a125; long a126; long a127; long a128; long a129; long a130; + long a131; long a132; long a133; long a134; long a135; long a136; long a137; long a138; long a139; long a140; + long a141; long a142; long a143; long a144; long a145; long a146; long a147; long a148; long a149; long a150; + long a151; long a152; long a153; long a154; long a155; long a156; long a157; long a158; long a159; long a160; + long a161; long a162; long a163; long a164; long a165; long a166; long a167; long a168; long a169; long a170; + long a171; long a172; long a173; long a174; long a175; long a176; long a177; long a178; long a179; long a180; + long a181; long a182; long a183; long a184; long a185; long a186; long a187; long a188; long a189; long a190; + long a191; long a192; long a193; long a194; long a195; long a196; long a197; long a198; long a199; long a200; + long a201; long a202; long a203; long a204; long a205; long a206; long a207; long a208; long a209; long a210; + long a211; long a212; long a213; long a214; long a215; long a216; long a217; long a218; long a219; long a220; + long a221; long a222; long a223; long a224; long a225; long a226; long a227; long a228; long a229; long a230; + long a231; long a232; long a233; long a234; long a235; long a236; long a237; long a238; long a239; long a240; + long a241; long a242; long a243; long a244; long a245; long a246; long a247; long a248; long a249; long a250; + #pragma warning restore 0169 + } + + class Program4 + { + [MethodImplAttribute(MethodImplOptions.NoInlining)] + static long test1(long l0, Test41 a, Test41 b, Test41 c, Test41 d) + { + #pragma warning disable 0168 + Offset1 offset; + #pragma warning restore 0168 + Console.WriteLine("test1: {0}", l0 + a.l1 + a.l2 + b.l1 + b.l2 + c.l1 + c.l2 + d.l1 + d.l2); + return l0 + a.l1 + a.l2 + b.l1 + b.l2 + c.l1 + c.l2 + d.l1 + d.l2; + } + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + static long test2(long l0, Test42 a, Test42 b, Test42 c, Test42 d) + { + #pragma warning disable 0168 + Offset1 offset; + #pragma warning restore 0168 + Console.WriteLine("test2: {0}", l0 + a.l1 + a.i1 + b.l1 + b.i1 + c.l1 + c.i1 + d.l1 + d.i1); + return l0 + a.l1 + a.i1 + b.l1 + b.i1 + c.l1 + c.i1 + d.l1 + d.i1; + } + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + static double test3(long l0, Test43 a, Test43 b, Test43 c, Test43 d) + { + #pragma warning disable 0168 + Offset1 offset; + #pragma warning restore 0168 + Console.WriteLine("test3: {0}", l0 + a.l1 + a.d1 + b.l1 + b.d1 + c.l1 + c.d1 + d.l1 + d.d1); + return l0 + a.l1 + a.d1 + b.l1 + b.d1 + c.l1 + c.d1 + d.l1 + d.d1; + } + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + static float test4(long l0, Test44 a, Test44 b, Test44 c, Test44 d) + { + #pragma warning disable 0168 + Offset1 offset; + #pragma warning restore 0168 + Console.WriteLine("test4: {0}", l0 + a.l1 + a.f1 + b.l1 + b.f1 + c.l1 + c.f1 + d.l1 + d.f1); + return l0 + a.l1 + a.f1 + b.l1 + b.f1 + c.l1 + c.f1 + d.l1 + d.f1; + } + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + static long test5(long l0, Test41 a, Test41 b, Test41 c, Test41 d) + { + #pragma warning disable 0168 + Offset2 offset; + #pragma warning restore 0168 + Console.WriteLine("test5: {0}", l0 + a.l1 + a.l2 + b.l1 + b.l2 + c.l1 + c.l2 + d.l1 + d.l2); + return l0 + a.l1 + a.l2 + b.l1 + b.l2 + c.l1 + c.l2 + d.l1 + d.l2; + } + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + static long test6(long l0, Test42 a, Test42 b, Test42 c, Test42 d) + { + #pragma warning disable 0168 + Offset2 offset; + #pragma warning restore 0168 + Console.WriteLine("test6: {0}", l0 + a.l1 + a.i1 + b.l1 + b.i1 + c.l1 + c.i1 + d.l1 + d.i1); + return l0 + a.l1 + a.i1 + b.l1 + b.i1 + c.l1 + c.i1 + d.l1 + d.i1; + } + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + static double test7(long l0, Test43 a, Test43 b, Test43 c, Test43 d) + { + #pragma warning disable 0168 + Offset2 offset; + #pragma warning restore 0168 + Console.WriteLine("test7: {0}", l0 + a.l1 + a.d1 + b.l1 + b.d1 + c.l1 + c.d1 + d.l1 + d.d1); + return l0 + a.l1 + a.d1 + b.l1 + b.d1 + c.l1 + c.d1 + d.l1 + d.d1; + } + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + static float test8(long l0, Test44 a, Test44 b, Test44 c, Test44 d) + { + #pragma warning disable 0168 + Offset2 offset; + #pragma warning restore 0168 + Console.WriteLine("test8: {0}", l0 + a.l1 + a.f1 + b.l1 + b.f1 + c.l1 + c.f1 + d.l1 + d.f1); + return l0 + a.l1 + a.f1 + b.l1 + b.f1 + c.l1 + c.f1 + d.l1 + d.f1; + } + + [MethodImplAttribute(MethodImplOptions.NoInlining)] + public static int Main1() + { + Test41 a1 = default(Test41); + Test41 b1 = default(Test41); + Test41 c1 = default(Test41); + Test41 d1 = default(Test41); + a1.l1 = 1; + a1.l2 = 2; + b1.l1 = 3; + b1.l2 = 4; + c1.l1 = 5; + c1.l2 = 6; + d1.l1 = 7; + d1.l2 = 8; + + Test42 a2 = default(Test42); + Test42 b2 = default(Test42); + Test42 c2 = default(Test42); + Test42 d2 = default(Test42); + a2.l1 = 1; + a2.i1 = 2; + b2.l1 = 3; + b2.i1 = 4; + c2.l1 = 5; + c2.i1 = 6; + d2.l1 = 7; + d2.i1 = 8; + + Test43 a3 = default(Test43); + Test43 b3 = default(Test43); + Test43 c3 = default(Test43); + Test43 d3 = default(Test43); + a3.l1 = 1; + a3.d1 = 2; + b3.l1 = 3; + b3.d1 = 4; + c3.l1 = 5; + c3.d1 = 6; + d3.l1 = 7; + d3.d1 = 8; + + Test44 a4 = default(Test44); + Test44 b4 = default(Test44); + Test44 c4 = default(Test44); + Test44 d4 = default(Test44); + a4.l1 = 1; + a4.f1 = 2; + b4.l1 = 3; + b4.f1 = 4; + c4.l1 = 5; + c4.f1 = 6; + d4.l1 = 7; + d4.f1 = 8; + + long t1Res = test1(9, a1, b1, c1, d1); + Console.WriteLine("test1 Result: {0}", t1Res); + if (t1Res != 45) + { + throw new Exception("Failed test1 test!"); + } + + long t2Res = test2(9, a2, b2, c2, d2); + Console.WriteLine("test2 Result: {0}", t2Res); + if (t1Res != 45) + { + throw new Exception("Failed test2 test!"); + } + + double t3Res = test3(9, a3, b3, c3, d3); + Console.WriteLine("test3 Result: {0}", t3Res); + if (t3Res != 45) + { + throw new Exception("Failed test3 test!"); + } + + float t4Res = test4(9, a4, b4, c4, d4); + Console.WriteLine("test4 Result: {0}", t4Res); + if (t4Res != 45) + { + throw new Exception("Failed test4 test!"); + } + + long t5Res = test5(9, a1, b1, c1, d1); + Console.WriteLine("test5 Result: {0}", t5Res); + if (t1Res != 45) + { + throw new Exception("Failed test1 test!"); + } + + long t6Res = test6(9, a2, b2, c2, d2); + Console.WriteLine("test6 Result: {0}", t6Res); + if (t6Res != 45) + { + throw new Exception("Failed test6 test!"); + } + + double t7Res = test7(9, a3, b3, c3, d3); + Console.WriteLine("test7 Result: {0}", t7Res); + if (t7Res != 45) + { + throw new Exception("Failed test7 test!"); + } + + float t8Res = test8(9, a4, b4, c4, d4); + Console.WriteLine("test8 Result: {0}", t8Res); + if (t8Res != 45) + { + throw new Exception("Failed test8 test!"); + } + + return 100; + } + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_87116/Runtime_87116.cs b/src/tests/JIT/Regression/JitBlue/Runtime_87116/Runtime_87116.cs new file mode 100644 index 00000000000000..13d4bcae32ace8 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_87116/Runtime_87116.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. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.Intrinsics; +using Xunit; + +public class Runtime_87116 +{ + [Fact] + public static int Test() + { + return TryVectorAdd(1, 2, 1 + 2) ? 100 : 0; + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static bool TryVectorAdd(float a, float b, float c) + { + Vector128 A = Vector128.Create(a); + Vector128 B = Vector128.Create(b); + + Vector128 C = A + B; + return C == Vector128.Create(c); + } +} diff --git a/src/tests/JIT/Regression/JitBlue/Runtime_87116/Runtime_87116.csproj b/src/tests/JIT/Regression/JitBlue/Runtime_87116/Runtime_87116.csproj new file mode 100644 index 00000000000000..de6d5e08882e86 --- /dev/null +++ b/src/tests/JIT/Regression/JitBlue/Runtime_87116/Runtime_87116.csproj @@ -0,0 +1,8 @@ + + + True + + + + + diff --git a/src/tests/Loader/AssemblyDependencyResolver/AssemblyDependencyResolverTests/AssemblyDependencyResolverTests.csproj b/src/tests/Loader/AssemblyDependencyResolver/AssemblyDependencyResolverTests/AssemblyDependencyResolverTests.csproj index 7ccf8f0fea739c..8f319017729c91 100644 --- a/src/tests/Loader/AssemblyDependencyResolver/AssemblyDependencyResolverTests/AssemblyDependencyResolverTests.csproj +++ b/src/tests/Loader/AssemblyDependencyResolver/AssemblyDependencyResolverTests/AssemblyDependencyResolverTests.csproj @@ -2,6 +2,8 @@ Exe true + + true diff --git a/src/tests/Loader/binding/tracing/BinderTracingTest.Basic.csproj b/src/tests/Loader/binding/tracing/BinderTracingTest.Basic.csproj index df0b34b275e4e6..aea7260ca1a9a8 100644 --- a/src/tests/Loader/binding/tracing/BinderTracingTest.Basic.csproj +++ b/src/tests/Loader/binding/tracing/BinderTracingTest.Basic.csproj @@ -2,6 +2,8 @@ true + + true diff --git a/src/tests/Loader/binding/tracing/BinderTracingTest.ResolutionFlow.csproj b/src/tests/Loader/binding/tracing/BinderTracingTest.ResolutionFlow.csproj index 3bc5ed34377a24..0bb68d9cb843d3 100644 --- a/src/tests/Loader/binding/tracing/BinderTracingTest.ResolutionFlow.csproj +++ b/src/tests/Loader/binding/tracing/BinderTracingTest.ResolutionFlow.csproj @@ -2,6 +2,8 @@ true + + true diff --git a/src/tests/Regressions/coreclr/GitHub_86865/test86865.cs b/src/tests/Regressions/coreclr/GitHub_86865/test86865.cs new file mode 100644 index 00000000000000..a8d65dea58be92 --- /dev/null +++ b/src/tests/Regressions/coreclr/GitHub_86865/test86865.cs @@ -0,0 +1,70 @@ +using System; +using System.Reflection; + +namespace test86865; + +public class test86865 +{ + public static int Main() + { + + // Regression test for https://github.com/dotnet/runtime/issues/86865 + // Verify that the RuntimeHelpers.GetSpanDataFrom method underlying RuntimeHelpers.CreateSpan + // works correctly with enums. + + ReadOnlySpan myEnums = new[] + { + MyEnum.A, + MyEnum.B, + MyEnum.C, + MyEnum.B, + MyEnum.C, + }; + + if (string.Join(", ", myEnums.ToArray()) != "A, B, C, B, C") + return 1; + + var types = new Type[] { + typeof(RuntimeFieldHandle), + typeof(RuntimeTypeHandle), + typeof(int).MakeByRefType(), + }; + var mi = typeof(System.Runtime.CompilerServices.RuntimeHelpers).GetMethod("GetSpanDataFrom", BindingFlags.Static | BindingFlags.NonPublic, types); + if (mi == null) + return 2; + + var pid = typeof(MyEnum).Assembly.GetType(""); + if (pid == null) + return 3; + + var fi = pid.GetField("0B77DC554B4A81403D62BE25FB5404020AD451151D4203D544BF60E3FEDBD8AE4", BindingFlags.Static | BindingFlags.NonPublic); + if (fi == null) + { + Console.WriteLine("Could not find the expected array data in . The available static non-public fields are:"); + foreach (var f in pid.GetFields(BindingFlags.Static | BindingFlags.NonPublic)) { + Console.WriteLine($" - '{f}'"); + } + return 4; + } + + var parms = new object[] { + fi.FieldHandle, + typeof(MyEnum).TypeHandle, + new int() + }; + var result = mi.Invoke(null, parms); + if (result == null) + return 6; + if ((int)parms[2] != myEnums.Length) + return 7; + + return 100; + } +} + +enum MyEnum +{ + A, + B, + C +} diff --git a/src/tests/Regressions/coreclr/GitHub_86865/test86865.csproj b/src/tests/Regressions/coreclr/GitHub_86865/test86865.csproj new file mode 100644 index 00000000000000..dc5ae5f51c138d --- /dev/null +++ b/src/tests/Regressions/coreclr/GitHub_86865/test86865.csproj @@ -0,0 +1,9 @@ + + + Exe + true + + + + + diff --git a/src/tests/baseservices/threading/coverage/OSThreadId/OSThreadId.cs b/src/tests/baseservices/threading/coverage/OSThreadId/OSThreadId.cs index 540e9d186a5247..0f774293af41c4 100644 --- a/src/tests/baseservices/threading/coverage/OSThreadId/OSThreadId.cs +++ b/src/tests/baseservices/threading/coverage/OSThreadId/OSThreadId.cs @@ -17,7 +17,7 @@ public sealed class OSThreadId public static int TestEntryPoint() { // The property to be tested is internal. - Type runtimeThreadType = typeof(object).Assembly.GetType("System.Threading.Thread"); + Type runtimeThreadType = Type.GetType("System.Threading.Thread"); Assert(runtimeThreadType != null); PropertyInfo osThreadIdProperty = runtimeThreadType.GetProperty("CurrentOSThreadId", BindingFlags.NonPublic | BindingFlags.Static); Assert(osThreadIdProperty != null); diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 9c2871386d86e4..8d1f6458a48bac 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -706,24 +706,6 @@ Just-in-time compilation test - - Not compatible with multifile testing. Problem with detecting that a JIT intrinsic is reflection-used. - - - Not compatible with multifile testing. Problem with detecting that a JIT intrinsic is reflection-used. - - - Not compatible with multifile testing. Problem with detecting that a JIT intrinsic is reflection-used. - - - Not compatible with multifile testing. Problem with detecting that a JIT intrinsic is reflection-used. - - - Not compatible with multifile testing. Problem with detecting that a JIT intrinsic is reflection-used. - - - Not compatible with multifile testing. Problem with detecting that a JIT intrinsic is reflection-used. - Not compatible with multifile testing. @@ -739,9 +721,6 @@ Specific to CoreCLR - - Accessing a reflection blocked internal detail - No crossgen folder under Core_Root @@ -943,15 +922,9 @@ Need to pass flag to enable object stack allocation in RyuJIT - - https://github.com/dotnet/runtimelab/issues/1136 - Multimodule incompatible (GVM) - - Needs triage - Needs triage @@ -1000,15 +973,6 @@ CoreCLR test - - https://github.com/dotnet/runtimelab/issues/165 - - - AOT incompatible - - - AOT incompatible - https://github.com/dotnet/runtimelab/issues/154 @@ -1087,9 +1051,6 @@ https://github.com/dotnet/runtime/issues/83051 - - https://github.com/dotnet/runtime/issues/83051 - https://github.com/dotnet/runtime/issues/83051 @@ -1114,9 +1075,6 @@ https://github.com/dotnet/runtime/issues/83051 - - https://github.com/dotnet/runtime/issues/83051 - https://github.com/dotnet/runtime/issues/83051 @@ -1174,6 +1132,27 @@ https://github.com/dotnet/runtimelab/issues/155: Assembly.LoadFrom + + https://github.com/dotnet/runtimelab/issues/155: Reflection.Emit + + + https://github.com/dotnet/runtimelab/issues/155: Reflection.Emit + + + https://github.com/dotnet/runtimelab/issues/155: Reflection.Emit + + + https://github.com/dotnet/runtimelab/issues/155: Reflection.Emit + + + https://github.com/dotnet/runtimelab/issues/155: Reflection.Emit + + + expects to see System.Private.CoreLib in CORE_ROOT + + + https://github.com/dotnet/runtime/issues/86990 + @@ -1233,13 +1212,10 @@ - - - - + true true + true + diff --git a/src/tests/tracing/eventpipe/reverse/reverse.csproj b/src/tests/tracing/eventpipe/reverse/reverse.csproj index a2fca0e2c1cca0..4b4bae03bc0b50 100644 --- a/src/tests/tracing/eventpipe/reverse/reverse.csproj +++ b/src/tests/tracing/eventpipe/reverse/reverse.csproj @@ -8,6 +8,7 @@ true true + true diff --git a/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs b/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs index 98b456626e093d..b6376efeef6f5a 100644 --- a/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs +++ b/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs @@ -1628,6 +1628,74 @@ protected void MarkField (FieldReference reference, DependencyInfo reason, in Me MarkField (field, reason, origin); } + void ReportWarningsForReflectionAccess (in MessageOrigin origin, MethodDefinition method, DependencyKind dependencyKind) + { + if (Annotations.ShouldSuppressAnalysisWarningsForRequiresUnreferencedCode (origin.Provider, out _)) + return; + + bool isReflectionAccessCoveredByRUC; + bool isCompilerGenerated = CompilerGeneratedState.IsNestedFunctionOrStateMachineMember (method); + bool forceRUCCheck = false; + RequiresUnreferencedCodeAttribute? requiresUnreferencedCode; + switch (dependencyKind) { + case DependencyKind.AttributeProperty: + // Property assignment in an attribute instance. + // This case is more like a direct method call than reflection, and should + // be logically similar to what is done in ReflectionMethodBodyScanner for method calls. + isReflectionAccessCoveredByRUC = Annotations.DoesMethodRequireUnreferencedCode (method, out requiresUnreferencedCode); + break; + + case DependencyKind.Ldftn: + case DependencyKind.Ldvirtftn: + case DependencyKind.Ldtoken: + // Compiler generated code accessed via a token is considered a "hard" reference + // even though we also have to treat it as reflection access. + // So we need to enforce RUC check/warn in this case. + forceRUCCheck = true; + isReflectionAccessCoveredByRUC = Annotations.ShouldSuppressAnalysisWarningsForRequiresUnreferencedCode (method, out requiresUnreferencedCode); + break; + + default: + // If the method being accessed has warnings suppressed due to Requires attributes, + // we need to issue a warning for the reflection access. This is true even for instance + // methods, which can be reflection-invoked without ever calling a constructor of the + // accessed type. + isReflectionAccessCoveredByRUC = Annotations.ShouldSuppressAnalysisWarningsForRequiresUnreferencedCode (method, out requiresUnreferencedCode); + break; + } + + if (isReflectionAccessCoveredByRUC && (!isCompilerGenerated || forceRUCCheck)) + ReportRequiresUnreferencedCode (method.GetDisplayName (), requiresUnreferencedCode!, new DiagnosticContext (origin, diagnosticsEnabled: true, Context)); + + bool isReflectionAccessCoveredByDAM = Annotations.FlowAnnotations.ShouldWarnWhenAccessedForReflection (method); + if (isReflectionAccessCoveredByDAM && (!isCompilerGenerated || forceRUCCheck)) { + // ReflectionMethodBodyScanner handles more cases for data flow annotations + // so don't warn for those. + switch (dependencyKind) { + case DependencyKind.AttributeConstructor: + case DependencyKind.AttributeProperty: + break; + default: + Context.LogWarning (origin, DiagnosticId.DynamicallyAccessedMembersMethodAccessedViaReflection, method.GetDisplayName ()); + break; + } + } + + // Warn on reflection access to compiler-generated methods, if the method isn't already unsafe to access via reflection + // due to annotations. For the annotation-based warnings, we skip virtual overrides since those will produce warnings on + // the base, but for unannotated compiler-generated methods this is not the case, so we must produce these warnings even + // for virtual overrides. This ensures that we include the unannotated MoveNext state machine method. Lambdas and local + // functions should never be virtual overrides in the first place. + bool isCoveredByAnnotations = isReflectionAccessCoveredByRUC || isReflectionAccessCoveredByDAM; + switch (dependencyKind) { + case DependencyKind.AccessedViaReflection: + case DependencyKind.DynamicallyAccessedMember: + if (ShouldWarnForReflectionAccessToCompilerGeneratedCode (method, isCoveredByAnnotations)) + Context.LogWarning (origin, DiagnosticId.CompilerGeneratedMemberAccessedViaReflection, method.GetDisplayName ()); + break; + } + } + void ReportWarningsForTypeHierarchyReflectionAccess (IMemberDefinition member, MessageOrigin origin) { Debug.Assert (member is MethodDefinition or FieldDefinition); @@ -1653,14 +1721,9 @@ static bool IsDeclaredWithinType (IMemberDefinition member, TypeDefinition type) if (reportOnMember) origin = new MessageOrigin (member); - - // All override methods should have the same annotations as their base methods - // (else we will produce warning IL2046 or IL2092 or some other warning). - // When marking override methods via DynamicallyAccessedMembers, we should only issue a warning for the base method. - bool skipWarningsForOverride = member is MethodDefinition m && m.IsVirtual && Annotations.GetBaseMethods (m) != null; - bool isReflectionAccessCoveredByRUC = Annotations.ShouldSuppressAnalysisWarningsForRequiresUnreferencedCode (member, out RequiresUnreferencedCodeAttribute? requiresUnreferencedCodeAttribute); - if (isReflectionAccessCoveredByRUC && !skipWarningsForOverride) { + bool isCompilerGenerated = CompilerGeneratedState.IsNestedFunctionOrStateMachineMember (member); + if (isReflectionAccessCoveredByRUC && !isCompilerGenerated) { var id = reportOnMember ? DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberWithRequiresUnreferencedCode : DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberOnBaseWithRequiresUnreferencedCode; Context.LogWarning (origin, id, type.GetDisplayName (), ((MemberReference) member).GetDisplayName (), // The cast is valid since it has to be a method or field @@ -1669,7 +1732,7 @@ static bool IsDeclaredWithinType (IMemberDefinition member, TypeDefinition type) } bool isReflectionAccessCoveredByDAM = Annotations.FlowAnnotations.ShouldWarnWhenAccessedForReflection (member); - if (isReflectionAccessCoveredByDAM && !skipWarningsForOverride) { + if (isReflectionAccessCoveredByDAM && !isCompilerGenerated) { var id = reportOnMember ? DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberWithDynamicallyAccessedMembers : DiagnosticId.DynamicallyAccessedMembersOnTypeReferencesMemberOnBaseWithDynamicallyAccessedMembers; Context.LogWarning (origin, id, type.GetDisplayName (), ((MemberReference) member).GetDisplayName ()); } @@ -3071,74 +3134,20 @@ void ProcessAnalysisAnnotationsForMethod (MethodDefinition method, DependencyKin // Don't warn for methods kept due to non-understood DebuggerDisplayAttribute // until https://github.com/dotnet/linker/issues/1873 is fixed. case DependencyKind.KeptForSpecialAttribute: - return; + break; case DependencyKind.DynamicallyAccessedMemberOnType: // DynamicallyAccessedMembers on type gets special treatment so that the warning origin // is the type or the annotated member. ReportWarningsForTypeHierarchyReflectionAccess (method, origin); - return; + break; default: // All other cases have the potential of us missing a warning if we don't report it // It is possible that in some cases we may report the same warning twice, but that's better than not reporting it. + ReportWarningsForReflectionAccess (origin, method, dependencyKind); break; }; - - if (Annotations.ShouldSuppressAnalysisWarningsForRequiresUnreferencedCode (origin.Provider, out _)) - return; - - bool skipWarningsForOverride; - bool isReflectionAccessCoveredByRUC; - RequiresUnreferencedCodeAttribute? requiresUnreferencedCode; - if (dependencyKind == DependencyKind.AttributeProperty) { - // Property assignment in an attribute instance. - // This case is more like a direct method call than reflection, and should - // be logically similar to what is done in ReflectionMethodBodyScanner for method calls. - skipWarningsForOverride = false; - isReflectionAccessCoveredByRUC = Annotations.DoesMethodRequireUnreferencedCode (method, out requiresUnreferencedCode); - } else { - // All override methods should have the same annotations as their base methods - // (else we will produce warning IL2046 or IL2092 or some other warning). - // When marking override methods via DynamicallyAccessedMembers, we should only issue a warning for the base method. - skipWarningsForOverride = dependencyKind == DependencyKind.DynamicallyAccessedMember && method.IsVirtual && Annotations.GetBaseMethods (method) != null; - // If the method being accessed has warnings suppressed due to Requires attributes, - // we need to issue a warning for the reflection access. This is true even for instance - // methods, which can be reflection-invoked without ever calling a constructor of the - // accessed type. - isReflectionAccessCoveredByRUC = Annotations.ShouldSuppressAnalysisWarningsForRequiresUnreferencedCode (method, out requiresUnreferencedCode); - } - - if (isReflectionAccessCoveredByRUC && !skipWarningsForOverride) - ReportRequiresUnreferencedCode (method.GetDisplayName (), requiresUnreferencedCode!, new DiagnosticContext (origin, diagnosticsEnabled: true, Context)); - - bool isReflectionAccessCoveredByDAM = Annotations.FlowAnnotations.ShouldWarnWhenAccessedForReflection (method); - if (isReflectionAccessCoveredByDAM && !skipWarningsForOverride) { - // ReflectionMethodBodyScanner handles more cases for data flow annotations - // so don't warn for those. - switch (dependencyKind) { - case DependencyKind.AttributeConstructor: - case DependencyKind.AttributeProperty: - break; - default: - Context.LogWarning (origin, DiagnosticId.DynamicallyAccessedMembersMethodAccessedViaReflection, method.GetDisplayName ()); - break; - } - } - - // Warn on reflection access to compiler-generated methods, if the method isn't already unsafe to access via reflection - // due to annotations. For the annotation-based warnings, we skip virtual overrides since those will produce warnings on - // the base, but for unannotated compiler-generated methods this is not the case, so we must produce these warnings even - // for virtual overrides. This ensures that we include the unannotated MoveNext state machine method. Lambdas and local - // functions should never be virtual overrides in the first place. - bool isCoveredByAnnotations = isReflectionAccessCoveredByRUC || isReflectionAccessCoveredByDAM; - switch (dependencyKind) { - case DependencyKind.AccessedViaReflection: - case DependencyKind.DynamicallyAccessedMember: - if (ShouldWarnForReflectionAccessToCompilerGeneratedCode (method, isCoveredByAnnotations)) - Context.LogWarning (origin, DiagnosticId.CompilerGeneratedMemberAccessedViaReflection, method.GetDisplayName ()); - break; - } } internal static void ReportRequiresUnreferencedCode (string displayName, RequiresUnreferencedCodeAttribute requiresUnreferencedCode, in DiagnosticContext diagnosticContext) diff --git a/src/tools/illink/src/linker/Linker/Driver.cs b/src/tools/illink/src/linker/Linker/Driver.cs index 539b83d7886bf2..5d646965a18a76 100644 --- a/src/tools/illink/src/linker/Linker/Driver.cs +++ b/src/tools/illink/src/linker/Linker/Driver.cs @@ -85,6 +85,8 @@ protected LinkContext Context { } } + private static readonly char[] s_separators = new char[] { ',', ';', ' ' }; + public Driver (Queue arguments) { this.arguments = arguments; @@ -852,7 +854,7 @@ static string Unquote (string arg) } value = Unquote (value); - string[] values = value.Split (new char[] { ',', ';', ' ' }, StringSplitOptions.RemoveEmptyEntries); + string[] values = value.Split (s_separators, StringSplitOptions.RemoveEmptyEntries); foreach (string v in values) { var id = v.Trim (); if (!id.StartsWith ("IL", StringComparison.Ordinal) || !ushort.TryParse (id.AsSpan (2), out ushort code)) 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 283f08e89446a7..abe939c2322b2b 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 @@ -15,7 +15,6 @@ namespace Mono.Linker.Tests.Cases.DataFlow { - [IgnoreTestCase ("Ignore in NativeAOT, see https://github.com/dotnet/runtime/issues/82447", IgnoredBy = Tool.NativeAot)] [SkipKeptItemsValidation] [ExpectedNoWarnings] class CompilerGeneratedCodeAccessedViaReflection @@ -29,6 +28,9 @@ public static void Main () LocalFunctions.Test (); SelfMarkingMethods.Test (); + DelegateAccess.Test (); + + DAMReflectionAccessToCompilerGeneratedCode.Test (); } class BaseTypeWithIteratorStateMachines @@ -55,9 +57,9 @@ public static IEnumerable IteratorWithoutDataflow () [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] [ExpectedWarning ("IL3002", "--MethodWithRequires--", - ProducedBy = Tool.Analyzer)] + ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] [ExpectedWarning ("IL3050", "--MethodWithRequires--", - ProducedBy = Tool.Analyzer)] + ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] [ExpectedWarning ("IL2119", "<" + nameof (IteratorCallsMethodWithRequires) + ">", "MoveNext", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] public static IEnumerable IteratorCallsMethodWithRequires () @@ -102,28 +104,24 @@ public static IEnumerable IteratorWithProblematicDataflow () } [ExpectedWarning ("IL2112", nameof (RUCTypeWithIterators) + "()", "--RUCTypeWithIterators--", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] + ProducedBy = Tool.Trimmer | Tool.NativeAot)] // warning about .ctor [RequiresUnreferencedCode ("--RUCTypeWithIterators--")] class RUCTypeWithIterators { - [ExpectedWarning ("IL2112", "<" + nameof (StaticIteratorCallsMethodWithRequires) + ">", "(Int32)", "--RUCTypeWithIterators--", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] // state machine ctor - [ExpectedWarning ("IL2112", nameof (StaticIteratorCallsMethodWithRequires) + "()", "--RUCTypeWithIterators--", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [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)] public static IEnumerable StaticIteratorCallsMethodWithRequires () { yield return 0; MethodWithRequires (); } - [ExpectedWarning ("IL2112", "<" + nameof (InstanceIteratorCallsMethodWithRequires) + ">", "(Int32)", "--RUCTypeWithIterators--", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] // state machine ctor [ExpectedWarning ("IL2112", nameof (InstanceIteratorCallsMethodWithRequires) + "()", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + 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)] public IEnumerable InstanceIteratorCallsMethodWithRequires () { yield return 0; @@ -144,11 +142,7 @@ public IEnumerable InstanceIteratorCallsMethodWithRequires () [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.StaticIteratorCallsMethodWithRequires) + ">", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2026", nameof (RUCTypeWithIterators.InstanceIteratorCallsMethodWithRequires) + "()", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2026", "<" + nameof (RUCTypeWithIterators.InstanceIteratorCallsMethodWithRequires) + ">", "(Int32)", - ProducedBy = Tool.Trimmer)] // state machine ctor + [ExpectedWarning ("IL2026", nameof (RUCTypeWithIterators.InstanceIteratorCallsMethodWithRequires) + "()")] [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithCorrectDataflow) + ">", "", ProducedBy = Tool.Trimmer)] [ExpectedWarning ("IL2118", "<" + nameof (IteratorWithProblematicDataflow) + ">", "", @@ -176,8 +170,8 @@ public static async Task AsyncWithoutDataflow () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] public static async Task AsyncCallsMethodWithRequires () { MethodWithRequires (); @@ -220,8 +214,8 @@ public static async IAsyncEnumerable AsyncIteratorWithoutDataflow () } [ExpectedWarning ("IL2026", "--MethodWithRequires--", CompilerGeneratedCode = true)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot, CompilerGeneratedCode = true)] public static async IAsyncEnumerable AsyncIteratorCallsMethodWithRequires () { yield return await MethodAsync (); @@ -272,8 +266,8 @@ static void LambdaCallsMethodWithRequires () { var lambda = [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] [ExpectedWarning ("IL2119", "<" + nameof (LambdaCallsMethodWithRequires) + ">", ProducedBy = Tool.Trimmer)] () => MethodWithRequires (); @@ -293,12 +287,10 @@ static void LambdaWithCorrectDataflow () } [ExpectedWarning ("IL2111", "<" + nameof (LambdaWithCorrectParameter) + ">", - ProducedBy = Tool.Trimmer)] + ProducedBy = Tool.Trimmer | Tool.NativeAot)] static void LambdaWithCorrectParameter () { var lambda = - [ExpectedWarning ("IL2114", "<" + nameof (LambdaWithCorrectParameter) + ">", - ProducedBy = Tool.Trimmer)] ([DynamicallyAccessedMembersAttribute (DynamicallyAccessedMemberTypes.All)] Type t) => { t.RequiresAll (); }; @@ -357,26 +349,22 @@ static void LambdaCallsPInvokeTakingObject () } [ExpectedWarning ("IL2112", nameof (RUCTypeWithLambdas) + "()", "--RUCTypeWithLambdas--", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] + ProducedBy = Tool.Trimmer | Tool.NativeAot)] [RequiresUnreferencedCode ("--RUCTypeWithLambdas--")] class RUCTypeWithLambdas { - [ExpectedWarning ("IL2112", nameof (MethodWithLambdas), "--RUCTypeWithLambdas--", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2112", nameof (MethodWithLambdas), "--RUCTypeWithLambdas--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] public void MethodWithLambdas () { var lambda = - [ExpectedWarning ("IL2112", "<" + nameof (MethodWithLambdas) + ">", "--RUCTypeWithLambdas--", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] () => MethodWithRequires (); int i = 0; var lambdaWithCapturedState = - [ExpectedWarning ("IL2112", "<" + nameof (MethodWithLambdas) + ">", "--RUCTypeWithLambdas--", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] () => { i++; MethodWithRequires (); @@ -393,18 +381,12 @@ public void MethodWithLambdas () ProducedBy = Tool.Trimmer)] [ExpectedWarning ("IL2118", "<" + nameof (LambdaWithCorrectDataflow) + ">", ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2111", "<" + nameof (LambdaWithCorrectParameter) + ">", - ProducedBy = Tool.Trimmer)] [ExpectedWarning ("IL2118", "<" + nameof (LambdaWithProblematicDataflow) + ">", ProducedBy = Tool.Trimmer)] [ExpectedWarning ("IL2118", "<" + nameof (LambdaWithCapturedTypeToDAM) + ">", ProducedBy = Tool.Trimmer)] [ExpectedWarning ("IL2026", nameof (RUCTypeWithLambdas) + "()", "--RUCTypeWithLambdas--")] - [ExpectedWarning ("IL2026", nameof (RUCTypeWithLambdas.MethodWithLambdas) + "()", "--RUCTypeWithLambdas--", ProducedBy = Tool.Trimmer | Tool.Analyzer)] - [ExpectedWarning ("IL2026", "<" + nameof (RUCTypeWithLambdas.MethodWithLambdas) + ">", "--RUCTypeWithLambdas--", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2026", "<" + nameof (RUCTypeWithLambdas.MethodWithLambdas) + ">", "--RUCTypeWithLambdas--", - ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2026", nameof (RUCTypeWithLambdas.MethodWithLambdas) + "()", "--RUCTypeWithLambdas--")] public static void Test (Lambdas test = null) { typeof (Lambdas).RequiresAll (); @@ -425,8 +407,8 @@ static void LocalFunctionWithoutDataflow () static void LocalFunctionCallsMethodWithRequires () { [ExpectedWarning ("IL2026", "--MethodWithRequires--")] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] [ExpectedWarning ("IL2119", "<" + nameof (LocalFunctionCallsMethodWithRequires) + ">", ProducedBy = Tool.Trimmer)] void LocalFunction () => MethodWithRequires (); @@ -494,31 +476,25 @@ static void LocalFunctionCallsPInvokeTakingObject () } [ExpectedWarning ("IL2112", nameof (RUCTypeWithLocalFunctions) + "()", CompilerGeneratedCode = true, - ProducedBy = Tool.Trimmer)] + ProducedBy = Tool.Trimmer | Tool.NativeAot)] [RequiresUnreferencedCode ("--RUCTypeWithLocalFunctions--")] class RUCTypeWithLocalFunctions { [ExpectedWarning ("IL2112", nameof (MethodWithLocalFunctions), "--RUCTypeWithLocalFunctions--", - ProducedBy = Tool.Trimmer)] + ProducedBy = Tool.Trimmer | Tool.NativeAot)] public void MethodWithLocalFunctions () { - [ExpectedWarning ("IL2112", "<" + nameof (MethodWithLocalFunctions) + ">", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] void LocalFunction () => MethodWithRequires (); - [ExpectedWarning ("IL2112", "<" + nameof (MethodWithLocalFunctions) + ">", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] static void StaticLocalFunction () => MethodWithRequires (); int i = 0; - [ExpectedWarning ("IL2112", "<" + nameof (MethodWithLocalFunctions) + ">", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL3002", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithRequires--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] void LocalFunctionWithCapturedState () { i++; @@ -543,13 +519,7 @@ void LocalFunctionWithCapturedState () ProducedBy = Tool.Trimmer)] // Expect RUC warnings for static, compiler-generated code warnings for instance. [ExpectedWarning ("IL2026", nameof (RUCTypeWithLocalFunctions) + "()", "--RUCTypeWithLocalFunctions--")] - [ExpectedWarning ("IL2026", "<" + nameof (RUCTypeWithLocalFunctions.MethodWithLocalFunctions) + ">", "LocalFunctionWithCapturedState", - ProducedBy = Tool.Trimmer)] // displayclass ctor - [ExpectedWarning ("IL2026", "<" + nameof (RUCTypeWithLocalFunctions.MethodWithLocalFunctions) + ">", "StaticLocalFunction", - ProducedBy = Tool.Trimmer)] - [ExpectedWarning ("IL2026", "<" + nameof (RUCTypeWithLocalFunctions.MethodWithLocalFunctions) + ">", "LocalFunction", - ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL2026", nameof (RUCTypeWithLocalFunctions.MethodWithLocalFunctions) + "()", ProducedBy = Tool.Trimmer | Tool.Analyzer)] + [ExpectedWarning ("IL2026", nameof (RUCTypeWithLocalFunctions.MethodWithLocalFunctions) + "()")] public static void Test (LocalFunctions test = null) { typeof (LocalFunctions).RequiresAll (); @@ -658,6 +628,121 @@ public static void Test () } } + class DelegateAccess + { + static void AnnotatedMethod ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) + { + } + + [ExpectedWarning ("IL2111", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + static void TestMethodThroughDelegate () + { + Action a = AnnotatedMethod; + } + + [ExpectedWarning ("IL2111", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + static void TestLambdaThroughDelegate () + { + Action a = ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) => { }; + a (null); + } + + [ExpectedWarning ("IL2111", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + static void TestLocalFunctionThroughDelegate () + { + Action a = LocalFunction; + a (null); + + void LocalFunction ([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type) + { + } + } + + static void TestGenericLocalFunctionThroughDelegate () + { + Action a = LocalFunction; + a (); + + void LocalFunction <[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () + { + } + } + + public static void Test () + { + TestMethodThroughDelegate (); + TestLambdaThroughDelegate (); + TestLocalFunctionThroughDelegate (); + TestGenericLocalFunctionThroughDelegate (); + } + } + + class DAMReflectionAccessToCompilerGeneratedCode + { + // ldftn access - this MUST warn since the action can be called without the annotation + [ExpectedWarning ("IL2111", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + static void Lambda () + { + Action a = ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) => { + type.GetMethods (); + }; + + a (typeof (string)); + } + + static void LambdaOnGeneric<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T> () + { + Action a = () => { + typeof(T).GetMethods (); + }; + + a (); + } + + static void LocalFunction () + { + LocalFunctionInner (typeof (string)); + + static void LocalFunctionInner ([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type) + { + type.GetMethods (); + } + } + + static void LocalFunctionOnGeneric<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>() + { + LocalFunctionInner (); + + static void LocalFunctionInner () + { + typeof(T).GetMethods (); + } + } + + static IEnumerable IteratorOnGeneric<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>() + { + yield return 0; + } + + static async Task AsyncOnGeneric<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () + { + await Task.Delay (100); + } + + static async IAsyncEnumerable AsyncIteratorOnGeneric<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> () + { + yield return 0; + await Task.Delay (100); + } + + [ExpectedWarning ("IL2118", "<" + nameof (LambdaOnGeneric) + ">", ProducedBy = Tool.Trimmer)] + [ExpectedWarning ("IL2118", "<" + nameof (LocalFunctionOnGeneric) + ">", ProducedBy = Tool.Trimmer)] + public static void Test () + { + typeof (DAMReflectionAccessToCompilerGeneratedCode).RequiresAll (); + } + } + [RequiresUnreferencedCode ("--MethodWithRequires--")] [RequiresAssemblyFiles ("--MethodWithRequires--")] [RequiresDynamicCode ("--MethodWithRequires--")] @@ -685,5 +770,7 @@ static async Task MethodAsync () [DllImport ("Foo")] static extern void MethodTakingObject ([MarshalAs (UnmanagedType.IUnknown)] object obj); + + class TestType { } } } 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 087a11bc038aa8..6c37b7dd3fe12b 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 @@ -3,8 +3,12 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; +using System.Reflection; +using System.Runtime.CompilerServices; using System.Text; +using System.Threading.Tasks; using Mono.Linker.Tests.Cases.Expectations.Assertions; using Mono.Linker.Tests.Cases.Expectations.Helpers; using Mono.Linker.Tests.Cases.Expectations.Metadata; @@ -57,6 +61,9 @@ public static void Main () RUCOnVirtualOnAnnotatedBase.Test (); RUCOnVirtualOnAnnotatedBaseUsedByDerived.Test (); UseByDerived.Test (); + + CompilerGeneratedCodeRUC.Test (null); + CompilerGeneratedCodeDAM.Test (null); } [Kept] @@ -277,8 +284,7 @@ class AnnotatedInterfaces : RequiredInterface { [Kept] [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] - // This should produce a warning: https://github.com/dotnet/linker/issues/2161 - [ExpectedWarning("IL2112", "--RUC on AnnotatedInterfaces.UnusedMethod--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2112", "--RUC on AnnotatedInterfaces.UnusedMethod--")] [RequiresUnreferencedCode ("--RUC on AnnotatedInterfaces.UnusedMethod--")] public void RUCMethod () { } } @@ -426,7 +432,7 @@ public void RUCMethod () { } [Kept] [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] - // shouldn't warn because we warn on the base method instead + [ExpectedWarning ("IL2112", "--AnnotatedDerivedFromBase.RUCVirtualMethod--")] [RequiresUnreferencedCode ("--AnnotatedDerivedFromBase.RUCVirtualMethod--")] public override void RUCVirtualMethod () { } @@ -438,9 +444,12 @@ public override void RUCVirtualMethod () { } [Kept] [KeptBackingField] [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))] - // shouldn't warn because we warn on the base getter instead [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicMethods)] - public override string DAMVirtualProperty { [Kept] get; } + public override string DAMVirtualProperty { + [Kept] + [ExpectedWarning ("IL2114", nameof (AnnotatedDerivedFromBase), nameof (DAMVirtualProperty))] + get; + } } @@ -463,7 +472,7 @@ public void RUCMethod () { } [Kept] [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] - // shouldn't warn because we warn on the base method instead + [ExpectedWarning ("IL2112", "--DerivedFromAnnotatedDerivedFromBase.RUCVirtualMethod--")] [RequiresUnreferencedCode ("--DerivedFromAnnotatedDerivedFromBase.RUCVirtualMethod--")] public override void RUCVirtualMethod () { } @@ -476,9 +485,12 @@ public override void RUCVirtualMethod () { } [Kept] [KeptBackingField] [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))] - // shouldn't warn because we warn on the base getter instead [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.NonPublicMethods)] - public override string DAMVirtualProperty { [Kept] get; } + public override string DAMVirtualProperty { + [Kept] + [ExpectedWarning ("IL2114", nameof (DerivedFromAnnotatedDerivedFromBase), nameof (DAMVirtualProperty))] + get; + } } [KeptMember (".ctor()")] @@ -629,8 +641,7 @@ public class Derived : Base [Kept] [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] [RequiresUnreferencedCode ("--RUCOnVirtualMethodDerivedAnnotated.Derived.RUCVirtualMethod--")] - // https://github.com/dotnet/linker/issues/2815 - [ExpectedWarning ("IL2112", "--RUCOnVirtualMethodDerivedAnnotated.Derived.RUCVirtualMethod--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2112", "--RUCOnVirtualMethodDerivedAnnotated.Derived.RUCVirtualMethod--")] public virtual void RUCVirtualMethod () { } } @@ -669,6 +680,7 @@ public class Derived : Base [Kept] [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] [RequiresUnreferencedCode ("--RUCOnVirtualMethodDerivedAnnotated.Derived.RUCVirtualMethod--")] + [ExpectedWarning ("IL2112", "--RUCOnVirtualMethodDerivedAnnotated.Derived.RUCVirtualMethod--")] public override void RUCVirtualMethod () { } } @@ -712,6 +724,7 @@ public class Derived : Base [Kept] [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] [RequiresUnreferencedCode ("--RUCOnVirtualMethodDerivedAnnotated.Derived.RUCVirtualMethod--")] + [ExpectedWarning ("IL2112", "--RUCOnVirtualMethodDerivedAnnotated.Derived.RUCVirtualMethod--")] public override void RUCVirtualMethod () { } } @@ -767,6 +780,7 @@ public static void MethodWithRequires () { } [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] [KeptAttributeAttribute (typeof (RequiresDynamicCodeAttribute))] [KeptAttributeAttribute (typeof (RequiresAssemblyFilesAttribute))] + [ExpectedWarning ("IL2112", "--Derived.VirtualMethodWithRequires--")] [RequiresUnreferencedCode ("--Derived.VirtualMethodWithRequires--")] [RequiresDynamicCode ("--Derived.VirtualMethodWithRequires--")] [RequiresAssemblyFiles ("--Derived.VirtualMethodWithRequires--")] @@ -846,5 +860,147 @@ public static void Test () derivedInstance.GetType ().RequiresNonPublicFields (); } } + + // This validates that marking compiler generated code via DAM-on-Type doesn't + // produce warnings about the compiler generated methods, even if they're in a RUC scope. + [Kept] + [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))] + [KeptMember (".ctor()")] + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] + class CompilerGeneratedCodeRUC + { + [Kept] + [ExpectedWarning ("IL2026", "LambdaWithRUC")] + static void LambdaWithRUC () + { + Action a = + [RequiresUnreferencedCode ("LambdaWithRUC")] + (Type type) => { type.GetMethods (); }; + + a (typeof (string)); + } + + [Kept] + [ExpectedWarning ("IL2026", "LocalFunctionWithRUC")] + static void LocalFunctionWithRUC () + { + LocalFunctionWithRUCInner (null); + + [RequiresUnreferencedCode ("LocalFunctionWithRUC")] + void LocalFunctionWithRUCInner (Type type) + { + type.GetMethods (); + } + } + + [Kept] + [KeptAttributeAttribute (typeof (IteratorStateMachineAttribute))] + [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] + [RequiresUnreferencedCode ("IteratorWithRUC")] + [ExpectedWarning ("IL2112", "IteratorWithRUC")] + static IEnumerable IteratorWithRUC () + { + yield return 1; + yield return 0; + } + + [Kept] + [KeptAttributeAttribute (typeof (AsyncStateMachineAttribute))] + [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] + [KeptAttributeAttribute (typeof (DebuggerStepThroughAttribute))] + [RequiresUnreferencedCode ("AsyncWithRUC")] + [ExpectedWarning ("IL2112", "AsyncWithRUC")] + static async Task AsyncWithRUC () + { + await Task.Delay (100); + } + + [Kept] + [KeptAttributeAttribute (typeof (AsyncIteratorStateMachineAttribute))] + [KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))] + [RequiresUnreferencedCode ("AsyncIteratorWithRUC")] + [ExpectedWarning ("IL2112", "AsyncIteratorWithRUC")] + static async IAsyncEnumerable AsyncIteratorWithRUC () + { + await Task.Delay (100); + yield return 1; + } + + [Kept] + public static void Test (CompilerGeneratedCodeRUC instance) + { + instance.GetType ().RequiresAll (); + } + } + + [Kept] + [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))] + [KeptMember (".ctor()")] + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.All)] + class CompilerGeneratedCodeDAM + { + [Kept] + [ExpectedWarning ("IL2111", nameof (LambdaWithDAM))] + static void LambdaWithDAM () + { + Action a = + ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) => { type.GetMethods (); }; + + a (typeof (string)); + } + + [Kept] + static void LocalFunctionWithDAM () + { + LocalFunctionWithDAMInner (typeof (string)); + + static void LocalFunctionWithDAMInner ([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] Type type) + { + type.GetMethods (); + } + } + + [Kept] + [KeptAttributeAttribute (typeof (IteratorStateMachineAttribute))] + [ExpectedWarning ("IL2119", nameof (IteratorWithGenericDAM), CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] + static IEnumerable IteratorWithGenericDAM< + [KeptAttributeAttribute(typeof(DynamicallyAccessedMembersAttribute))] + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T> () + { + foreach (MethodInfo m in typeof (T).GetMethods ()) + yield return m.IsPublic; + } + + [Kept] + [KeptAttributeAttribute (typeof (AsyncStateMachineAttribute))] + [KeptAttributeAttribute (typeof (DebuggerStepThroughAttribute))] + [ExpectedWarning ("IL2119", nameof (AsyncWithGenericDAM), CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] + static async Task AsyncWithGenericDAM< + [KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))] + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>() + { + await Task.Delay (100); + typeof (T).GetMethods (); + } + + [Kept] + [KeptAttributeAttribute (typeof (AsyncIteratorStateMachineAttribute))] + [ExpectedWarning("IL2119", nameof(AsyncIteratorWithGenericDAM), CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] + static async IAsyncEnumerable AsyncIteratorWithGenericDAM< + [KeptAttributeAttribute(typeof(DynamicallyAccessedMembersAttribute))] + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicMethods)] T>() + { + foreach (MethodInfo m in typeof (T).GetMethods ()) { + await Task.Delay (100); + yield return m.IsPublic; + } + } + + [Kept] + public static void Test (CompilerGeneratedCodeDAM instance) + { + instance.GetType ().RequiresAll (); + } + } } } 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 f58b051b4a3e96..6aa4bc0e78370f 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 @@ -26,9 +26,6 @@ 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 ("IL2026", "--MethodWithLocalFunctionWithRUC.LocalFunction--", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithLocalFunctionWithRUC.LocalFunction--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithLocalFunctionWithRUC.LocalFunction--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] [ExpectedWarning ("IL2111", nameof (TypeWithMethodWithRequires.MethodWithAnnotations), CompilerGeneratedCode = true)] @@ -50,9 +47,6 @@ 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 ("IL2026", "--MethodWithLocalFunctionWithRUC.LocalFunction--", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithLocalFunctionWithRUC.LocalFunction--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithLocalFunctionWithRUC.LocalFunction--", CompilerGeneratedCode = true, ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", CompilerGeneratedCode = true, ProducedBy = Tool.Trimmer)] [ExpectedWarning ("IL2111", nameof (TypeWithMethodWithRequires.MethodWithAnnotations), CompilerGeneratedCode = true)] @@ -79,7 +73,7 @@ static async void TestAsyncWithRUC () [ExpectedWarning ("IL3050", "--TestAsyncWithRUC--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] public static void Test () { - TestIterator ().GetEnumerator ().MoveNext (); // Must actually une the enumerator, otherwise NativeAOT will trim the implementation + TestIterator ().GetEnumerator ().MoveNext (); // Must actually use the enumerator, otherwise NativeAOT will trim the implementation TestIteratorWithRUC (); TestAsync (); TestAsyncWithRUC (); @@ -93,9 +87,6 @@ static void TestLocalFunction () [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--")] [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--MethodWithLocalFunctionWithRUC.LocalFunction--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithLocalFunctionWithRUC.LocalFunction--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithLocalFunctionWithRUC.LocalFunction--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", ProducedBy = Tool.Trimmer)] [ExpectedWarning ("IL2111", nameof (TypeWithMethodWithRequires.MethodWithAnnotations))] @@ -152,9 +143,6 @@ static void TestLambda () [ExpectedWarning ("IL2026", "--TypeWithMethodWithRequires.MethodWithRequires--")] [ExpectedWarning ("IL3002", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--TypeWithMethodWithRequires.MethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--MethodWithLocalFunctionWithRUC.LocalFunction--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--MethodWithLocalFunctionWithRUC.LocalFunction--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--MethodWithLocalFunctionWithRUC.LocalFunction--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2118", nameof (TypeWithMethodWithRequires.MethodWithLocalFunctionCallsRUC), "LocalFunction", ProducedBy = Tool.Trimmer)] [ExpectedWarning ("IL2111", nameof (TypeWithMethodWithRequires.MethodWithAnnotations))] 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 15c0993c7a9531..848d2b02669a4a 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 @@ -22,7 +22,6 @@ public static void Main () { TestRequiresOnlyThroughReflection (); AccessedThroughReflectionOnGenericType.Test (); - AccessedThroughGenericParameterAnnotation.Test (); AccessThroughSpecialAttribute.Test (); AccessThroughPInvoke.Test (); AccessThroughNewConstraint.Test (); @@ -31,6 +30,7 @@ public static void Main () AccessThroughNewConstraint.TestNewConstraintOnTypeParameterInAnnotatedMethod (); AccessThroughNewConstraint.TestNewConstraintOnTypeParameterInAnnotatedType (); AccessThroughLdToken.Test (); + AccessThroughDelegate.Test (); } class TestType { } @@ -74,59 +74,6 @@ public static void Test () } } - class AccessedThroughGenericParameterAnnotation - { - class TypeWithRequiresMethod - { - [RequiresUnreferencedCode("--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] - [RequiresDynamicCode ("--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] - [RequiresAssemblyFiles ("--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] - public static void MethodWhichRequires () { } - } - - class TypeWithPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> - { - public TypeWithPublicMethods () { } - } - - [ExpectedWarning ("IL2026", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] - [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] - static void TestAccessOnGenericType () - { - new TypeWithPublicMethods (); - } - - 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)] - static void TestAccessOnGenericMethod () - { - MethodWithPublicMethods (); - } - - static void MethodWithPublicMethodsInference<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> (T instance) { } - - // https://github.com/dotnet/runtime/issues/86032 - // IL2026 should be produced by the analyzer as well, but it has a bug around inferred generic arguments - [ExpectedWarning ("IL2026", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] - static void TestAccessOnGenericMethodWithInferenceOnMethod () - { - MethodWithPublicMethodsInference (new TypeWithRequiresMethod ()); - } - - public static void Test () - { - TestAccessOnGenericType (); - TestAccessOnGenericMethod (); - TestAccessOnGenericMethodWithInferenceOnMethod (); - } - } - class AccessThroughSpecialAttribute { // https://github.com/dotnet/linker/issues/1873 @@ -284,10 +231,99 @@ static bool PropertyWithLdToken { [ExpectedWarning ("IL3002", "--PropertyWithLdToken.get--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--PropertyWithLdToken.get--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] [ExpectedWarning ("IL3050", "--PropertyWithLdToken.get--", ProducedBy = Tool.NativeAot)] - public static void Test () + static void TestPropertyLdToken () { Expression> getter = () => PropertyWithLdToken; } + + [RequiresUnreferencedCode ("Message for --MethodWithLdToken--")] + [RequiresAssemblyFiles ("Message for --MethodWithLdToken--")] + [RequiresDynamicCode ("Message for --MethodWithLdToken--")] + static void MethodWithLdToken () + { + } + + [ExpectedWarning ("IL2026", "--MethodWithLdToken--")] + [ExpectedWarning ("IL3002", "--MethodWithLdToken--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithLdToken--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + static void TestMethodLdToken () + { + Expression e = () => MethodWithLdToken (); + } + + [RequiresUnreferencedCode ("--FieldWithLdToken--")] + [RequiresDynamicCode ("--FieldWithLdToken--")] + class FieldWithLdTokenType + { + public static int Field = 0; + } + + [ExpectedWarning ("IL2026", "--FieldWithLdToken--")] + [ExpectedWarning ("IL3050", "--FieldWithLdToken--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + static void TestFieldLdToken () + { + Expression> f = () => FieldWithLdTokenType.Field; + } + + public static void Test () + { + TestPropertyLdToken (); + TestMethodLdToken (); + TestFieldLdToken (); + } + } + + class AccessThroughDelegate + { + [RequiresUnreferencedCode ("Message for --MethodWithDelegate--")] + [RequiresAssemblyFiles ("Message for --MethodWithDelegate--")] + [RequiresDynamicCode ("Message for --MethodWithDelegate--")] + static void MethodWithDelegate () + { + } + + [ExpectedWarning ("IL2026", "--MethodWithDelegate--")] + [ExpectedWarning ("IL3002", "--MethodWithDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--MethodWithDelegate--", ProducedBy = 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)] + static void LambdaThroughDelegate () + { + Action a = + [RequiresUnreferencedCode ("--LambdaThroughDelegate--")] + [RequiresAssemblyFiles ("--LambdaThroughDelegate--")] + [RequiresDynamicCode ("--LambdaThroughDelegate--")] + () => { }; + + a (); + } + + [ExpectedWarning ("IL2026", "--LocalFunctionThroughDelegate--")] + [ExpectedWarning ("IL3002", "--LocalFunctionThroughDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--LocalFunctionThroughDelegate--", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + static void LocalFunctionThroughDelegate () + { + Action a = Local; + + [RequiresUnreferencedCode ("--LocalFunctionThroughDelegate--")] + [RequiresAssemblyFiles ("--LocalFunctionThroughDelegate--")] + [RequiresDynamicCode ("--LocalFunctionThroughDelegate--")] + void Local () + { } + } + + public static void Test () + { + TestMethodWithDelegate (); + LambdaThroughDelegate (); + LocalFunctionThroughDelegate (); + } } } } 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 e5b28b192b7639..6e2fcca2875db4 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 @@ -22,7 +22,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability class RequiresAttributeMismatch { // General comment about IL3003 - // Analyzer looks at properties, events and method separately. So mistmatch on property level will be reported + // Analyzer looks at properties, events and methods separately. So mismatch on property level will be reported // only on the property and not on the accessors. And vice versa. // NativeAOT doesn't really see properties and events, only methods. So it is much easier to handle everything // on the method level. While it's a discrepancy in behavior, it's small and should have no adverse effects @@ -31,8 +31,6 @@ class RequiresAttributeMismatch // then both accessors will report IL3003 (the attribute on the property is treated as if it was specified // on all accessors, always). // This discrepancy is tracked by https://github.com/dotnet/runtime/issues/83235. - - // Base/Derived and Implementation/Interface differs between ILLink and analyzer https://github.com/dotnet/linker/issues/2533 [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get")] [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] @@ -42,11 +40,20 @@ class RequiresAttributeMismatch [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get")] [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "DerivedClassWithRequires.VirtualPropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.set", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.get", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.set", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.Analyzer)] + [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 ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.set")] + [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInAccesor.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.get")] + [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.get", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.set")] + [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInProperty.set", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInPropertyAndAccessor.set")] + [ExpectedWarning ("IL3002", "DerivedClassWithAllWarnings.VirtualPropertyAnnotationInPropertyAndAccessor.set", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualMethod()")] [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] @@ -56,7 +63,9 @@ class RequiresAttributeMismatch [ExpectedWarning ("IL2026", "BaseClassWithRequires.VirtualMethod()")] [ExpectedWarning ("IL3002", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "BaseClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "DerivedClassWithRequires.VirtualMethod()", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "DerivedClassWithRequires.VirtualMethod()")] + [ExpectedWarning ("IL3002", "DerivedClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "DerivedClassWithRequires.VirtualMethod()", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2026", "IBaseWithRequires.PropertyAnnotationInAccesor.get")] [ExpectedWarning ("IL3002", "IBaseWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "IBaseWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] @@ -68,23 +77,23 @@ class RequiresAttributeMismatch [ExpectedWarning ("IL2026", "IBaseWithRequires.Method()")] [ExpectedWarning ("IL3002", "IBaseWithRequires.Method()", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "IBaseWithRequires.Method()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "ImplementationClassWithRequires.Method()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "ImplementationClassWithRequires.Method()")] [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.Method()", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "ImplementationClassWithRequires.Method()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get")] [ExpectedWarning ("IL3002", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "ImplementationClassWithRequires.PropertyAnnotationInAccesor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "ImplementationClassWithRequires.PropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.Analyzer | 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 ("IL2026", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get")] [ExpectedWarning ("IL3002", "ImplementationClassWithoutRequires.PropertyAnnotationInPropertyAndAccessor.get", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "ImplementationClassWithRequiresInSource.Method()", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "ImplementationClassWithRequiresInSource.Method()")] [ExpectedWarning ("IL3002", "ImplementationClassWithRequiresInSource.Method()", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "ImplementationClassWithRequiresInSource.Method()", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "ImplementationClassWithRequiresInSource.PropertyAnnotationInAccesor.get", ProducedBy = Tool.Analyzer | 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)] 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 06179031c754bb..37c9da005fb07f 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 @@ -44,6 +44,8 @@ public static void Main () ComplexCases.AsyncBodyCallingMethodWithRequires.Test (); ComplexCases.GenericAsyncBodyCallingMethodWithRequires.Test (); ComplexCases.GenericAsyncEnumerableBodyCallingRequiresWithAnnotations.Test (); + + RUCOnDelegateCacheFields.Test (); } class WarnInIteratorBody @@ -1880,59 +1882,6 @@ static async void TestAsyncOnlyReferencedViaReflectionWhichShouldWarn () [ExpectedWarning ("IL2026", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--")] [ExpectedWarning ("IL3002", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - // Analyzer doesn't emit additional warnings about reflection access to the compiler-generated - // state machine members. - [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - - // The MoveNext, Current.get and Reset methods produces warning in NativeAOT - // https://github.com/dotnet/runtime/issues/82447 - [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestIteratorOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] -#if !RELEASE - [ExpectedWarning ("IL2026", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - // In debug mode, the async state machine is a class with a constructor, so a warning is emitted for the constructor. - // The MoveNext method is virtual, so doesn't warn either way. -#else - // In release mode, the async state machine is a struct which doesn't have a constructor, so no warning is emitted. -#endif - // The MoveNext method produces warning in NativeAOT - // https://github.com/dotnet/runtime/issues/82447 - [ExpectedWarning ("IL2026", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestAsyncOnlyReferencedViaReflectionWhichShouldSuppress--", ProducedBy = Tool.NativeAot)] - [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()", @@ -2045,24 +1994,6 @@ void LocalFunction () [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--")] [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] - // Trimming tools correctly emit warnings about reflection access to local functions with Requires - // or which inherit Requires from the containing method. The analyzer doesn't bind to local functions - // so does not warn here. - [ExpectedWarning ("IL2026", "--TestLocalFunctionWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithClosureWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithClosureWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2118", nameof (LocalFunctionsReferencedViaReflection), nameof (TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection), ProducedBy = Tool.Trimmer)] static void TestAll () @@ -2080,22 +2011,6 @@ static void TestAll () [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--")] [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] - // NonPublicMethods warns for local functions not emitted into display classes. - [ExpectedWarning ("IL2026", "--TestLocalFunctionWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithRequiresOnlyAccessedViaReflection--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithClosureWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithClosureWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLocalFunctionWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2118", nameof (LocalFunctionsReferencedViaReflection), "<" + nameof (TestLocalFunctionInMethodWithRequiresOnlyAccessedViaReflection) + ">", ProducedBy = Tool.Trimmer)] static void TestNonPublicMethods () @@ -2173,21 +2088,6 @@ static void TestLambdaWithClosureInMethodWithRequires (int p = 0) [ExpectedWarning ("IL2026", "--TestLambdaWithClosureInMethodWithRequires--")] [ExpectedWarning ("IL3002", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - // Trimming tools correctly emit warnings about reflection access to lambdas with Requires - // or which inherit Requires from the containing method. The analyzer doesn't bind to lambdas - // so does not warn here. - [ExpectedWarning ("IL2026", "--TestLambdaWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLambdaWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLambdaWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLambdaWithClosureWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLambdaWithClosureWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLambdaWithClosureWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLambdaInMethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLambdaInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLambdaInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] - [ExpectedWarning ("IL3002", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] static void TestAll () { typeof (LambdasReferencedViaReflection).RequiresAll (); @@ -2200,7 +2100,6 @@ static void TestAll () [ExpectedWarning ("IL2026", "--TestLambdaWithClosureInMethodWithRequires--")] [ExpectedWarning ("IL3002", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--TestLambdaWithClosureInMethodWithRequires--", ProducedBy = Tool.NativeAot)] - // NonPublicMethods doesn't warn for lambdas emitted into display class types. static void TestNonPublicMethods () { typeof (LambdasReferencedViaReflection).RequiresNonPublicMethods (); @@ -2318,6 +2217,25 @@ class Disposable : IDisposable { public void Dispose () { } } static Task GetDisposableAsync () { return Task.FromResult (new Disposable ()); } } + class RUCOnDelegateCacheFields + { + [RequiresUnreferencedCode ("--RUCOnDelegateCacheFields.TargetType--")] + class TargetType + { + public static void Init () + { + var Action = () => { }; + } + } + + [ExpectedWarning ("IL2026", nameof (TargetType) + "()")] // .ctor + [ExpectedWarning ("IL2026", nameof (TargetType.Init) + "()")] // Init method + public static void Test () + { + typeof (TargetType).RequiresAll (); + } + } + static async Task MethodAsync () { return await Task.FromResult (0); 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 2ae2c7fb2002b4..24faa7879210f5 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 @@ -535,24 +535,18 @@ class ReflectionAccessOnMethod [ExpectedWarning ("IL3050", "BaseWithoutRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2026", "BaseWithoutRequiresOnType.Method()")] [ExpectedWarning ("IL3050", "BaseWithoutRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] - // https://github.com/dotnet/linker/issues/2533 - [ExpectedWarning ("IL2026", "DerivedWithRequiresOnType.Method()", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "DerivedWithRequiresOnType.Method()")] + [ExpectedWarning ("IL3050", "DerivedWithRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2026", "InterfaceWithoutRequires.Method(Int32)")] [ExpectedWarning ("IL3050", "InterfaceWithoutRequires.Method(Int32)", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2026", "InterfaceWithoutRequires.Method()")] [ExpectedWarning ("IL3050", "InterfaceWithoutRequires.Method()", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL2026", "ImplementationWithRequiresOnType.Method()")] [ExpectedWarning ("IL3050", "ImplementationWithRequiresOnType.Method()", ProducedBy = Tool.NativeAot)] - // https://github.com/dotnet/linker/issues/2533 - // NativeAOT has a correct override resolution and in this case the method is not an override - so it should warn - [ExpectedWarning ("IL2026", "ImplementationWithRequiresOnType.Method(Int32)", ProducedBy = Tool.Analyzer | Tool.NativeAot)] + [ExpectedWarning ("IL2026", "ImplementationWithRequiresOnType.Method(Int32)")] [ExpectedWarning ("IL3050", "ImplementationWithRequiresOnType.Method(Int32)", ProducedBy = Tool.NativeAot)] - // ILLink incorrectly skips warnings for derived method, under the assumption that - // it will be covered by the base method. But in this case the base method - // is unannotated (and the mismatch produces no warning because the derived - // type has RUC). - // https://github.com/dotnet/linker/issues/2533 - [ExpectedWarning ("IL2026", "DerivedWithRequiresOnTypeOverBaseWithNoRequires.Method()", ProducedBy = Tool.Analyzer)] + [ExpectedWarning ("IL2026", "DerivedWithRequiresOnTypeOverBaseWithNoRequires.Method()")] + [ExpectedWarning ("IL3050", "DerivedWithRequiresOnTypeOverBaseWithNoRequires.Method()", ProducedBy = Tool.NativeAot)] static void TestDAMAccess () { // Warns because BaseWithoutRequiresOnType.Method has Requires on the method @@ -814,6 +808,28 @@ static void TestDAMOnTypeAccessInRUCScope (DAMAnnotatedClassAccessedFromRUCScope instance.GetType ().GetMethod ("RUCMethod"); } + [RequiresUnreferencedCode ("--GenericTypeWithRequires--")] + [RequiresDynamicCode ("--GenericTypeWithRequires--")] + class GenericTypeWithRequires + { + public static int NonGenericField; + } + + // https://github.com/dotnet/runtime/issues/86633 - analyzer doesn't report this warning + [ExpectedWarning ("IL2026", "NonGenericField", "--GenericTypeWithRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL3050", "NonGenericField", "--GenericTypeWithRequires--", ProducedBy = Tool.NativeAot)] + static void TestDAMAccessOnOpenGeneric () + { + typeof (GenericTypeWithRequires<>).RequiresPublicFields (); + } + + [ExpectedWarning ("IL2026", "NonGenericField", "--GenericTypeWithRequires--")] + [ExpectedWarning ("IL3050", "NonGenericField", "--GenericTypeWithRequires--", ProducedBy = Tool.NativeAot)] + static void TestDAMAccessOnInstantiatedGeneric () + { + typeof (GenericTypeWithRequires).RequiresPublicFields (); + } + [ExpectedWarning ("IL2026", "--TestDAMOnTypeAccessInRUCScope--")] public static void Test () { @@ -822,6 +838,8 @@ public static void Test () TestDynamicDependencyAccess (); TestDAMOnTypeAccess (null); TestDAMOnTypeAccessInRUCScope (); + TestDAMAccessOnOpenGeneric (); + TestDAMAccessOnInstantiatedGeneric (); } } 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 5470aa11717873..fa821b58e99730 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 @@ -76,9 +76,6 @@ static void TestCallOnOverrideViaBase () tmp.VirtualMethodRequires (); } - // https://github.com/dotnet/runtime/issues/86008 - // This is the "direct reflection" case, which actually behaves differently from indirect (DAM annotation) - // in this case even trimmer will warn on both methods. [ExpectedWarning ("IL2026", "--BaseType.VirtualMethodRequires--")] [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] @@ -96,13 +93,12 @@ static void TestDirectReflectionAccess () typeof(T).GetMethod("VirtualMethodRequires").Invoke(instance, Array.Empty ()); } - // https://github.com/dotnet/runtime/issues/86008 [ExpectedWarning ("IL2026", "--BaseType.VirtualMethodRequires--")] [ExpectedWarning ("IL3002", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL2026", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.Analyzer)] - //[ExpectedWarning ("IL3002", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] - //[ExpectedWarning ("IL3050", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL2026", "--TypeWhichOverridesMethod.VirtualMethodRequires--")] + [ExpectedWarning ("IL3002", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] static void TestAnnotatedReflectionAccess() { CallMethodWithRequiresOnInstance(new TypeWhichOverridesMethod ()); @@ -209,9 +205,7 @@ static void TestDirectReflectionAccess () typeof (T).GetMethod ("MethodWithRequires").Invoke (new ImplementationClass (), Array.Empty ()); } - // https://github.com/dotnet/runtime/issues/86008 - // This is a bug in illink, the fact that there's no warning is an analysis hole - [ExpectedWarning ("IL2026", "--ImplementationClass.RequiresMethod--", ProducedBy = Tool.NativeAot | Tool.Analyzer)] + [ExpectedWarning ("IL2026", "--ImplementationClass.RequiresMethod--")] [ExpectedWarning ("IL3002", "--ImplementationClass.RequiresMethod--", ProducedBy = Tool.NativeAot)] [ExpectedWarning ("IL3050", "--ImplementationClass.RequiresMethod--", ProducedBy = Tool.NativeAot)] static void TestAnnotatedReflectionAccess () @@ -317,8 +311,7 @@ public virtual void 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)] - // https://github.com/dotnet/linker/issues/2815 - [ExpectedWarning ("IL2026", "Message for --NewSlotVirtual.Derived.RUCMethod--", ProducedBy = Tool.Analyzer | 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)] 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 15dd829a93a198..a88250de5683d8 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 @@ -15,66 +15,142 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability [ExpectedNoWarnings] class RequiresViaDataflow { - // Base/Derived and Implementation/Interface differs between ILLink and analyzer https://github.com/dotnet/linker/issues/2533 - [ExpectedWarning ("IL2026", "--DynamicallyAccessedTypeWithRequires.MethodWithRequires--")] - [ExpectedWarning ("IL2026", "TypeWhichOverridesMethod.VirtualMethodRequires()", "--TypeWhichOverridesMethod.VirtualMethodRequires--", ProducedBy = Tool.Analyzer)] - [ExpectedWarning ("IL2026", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--")] - [ExpectedWarning ("IL3002", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] - [ExpectedWarning ("IL3050", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] public static void Main () { - TestDynamicallyAccessedMembersWithRequires (typeof (DynamicallyAccessedTypeWithRequires)); - TestDynamicallyAccessedMembersWithRequires (typeof (TypeWhichOverridesMethod)); - TestRequiresInDynamicDependency (); + AnnotatedParameter.Test (); + AnnotatedGenericParameter.Test (); + DynamicDependency.Test (); } - class BaseType + class AnnotatedParameter { - [RequiresUnreferencedCode ("Message for --BaseType.VirtualMethodRequires--")] - [RequiresAssemblyFiles ("Message for --BaseType.VirtualMethodRequires--")] - [RequiresDynamicCode ("Message for --BaseType.VirtualMethodRequires--")] - public virtual void VirtualMethodRequires () + static void MethodWithAnnotatedParameter ( + [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) { } - } - class TypeWhichOverridesMethod : BaseType - { - [RequiresUnreferencedCode ("Message for --TypeWhichOverridesMethod.VirtualMethodRequires--")] - [RequiresAssemblyFiles ("Message for --TypeWhichOverridesMethod.VirtualMethodRequires--")] - [RequiresDynamicCode ("Message for --TypeWhichOverridesMethod.VirtualMethodRequires--")] - public override void VirtualMethodRequires () + public class DynamicallyAccessedTypeWithRequires { + [RequiresUnreferencedCode ("Message for --DynamicallyAccessedTypeWithRequires.MethodWithRequires--")] + public void MethodWithRequires () + { + } } - } - public class DynamicallyAccessedTypeWithRequires - { - [RequiresUnreferencedCode ("Message for --DynamicallyAccessedTypeWithRequires.MethodWithRequires--")] - public void MethodWithRequires () + [ExpectedWarning ("IL2026", "--DynamicallyAccessedTypeWithRequires.MethodWithRequires--")] + static void TestNonVirtualMethod () { + MethodWithAnnotatedParameter (typeof (DynamicallyAccessedTypeWithRequires)); } - } - static void TestDynamicallyAccessedMembersWithRequires ( - [DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] Type type) - { + class BaseType + { + [RequiresUnreferencedCode ("Message for --BaseType.VirtualMethodRequires--")] + [RequiresAssemblyFiles ("Message for --BaseType.VirtualMethodRequires--")] + [RequiresDynamicCode ("Message for --BaseType.VirtualMethodRequires--")] + public virtual void VirtualMethodRequires () + { + } + } + + class TypeWhichOverridesMethod : BaseType + { + [RequiresUnreferencedCode ("Message for --TypeWhichOverridesMethod.VirtualMethodRequires--")] + [RequiresAssemblyFiles ("Message for --TypeWhichOverridesMethod.VirtualMethodRequires--")] + [RequiresDynamicCode ("Message for --TypeWhichOverridesMethod.VirtualMethodRequires--")] + 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 ("IL2026", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--")] + [ExpectedWarning ("IL3002", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "BaseType.VirtualMethodRequires()", "--BaseType.VirtualMethodRequires--", ProducedBy = Tool.NativeAot)] + static void TestOverriddenVirtualMethod () + { + MethodWithAnnotatedParameter (typeof (TypeWhichOverridesMethod)); + } + + public static void Test () + { + TestNonVirtualMethod (); + TestOverriddenVirtualMethod (); + } } - [RequiresUnreferencedCode ("Message for --RequiresInDynamicDependency--")] - [RequiresAssemblyFiles ("Message for --RequiresInDynamicDependency--")] - [RequiresDynamicCode ("Message for --RequiresInDynamicDependency--")] - static void RequiresInDynamicDependency () + class AnnotatedGenericParameter { + class TypeWithRequiresMethod + { + [RequiresUnreferencedCode ("--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] + [RequiresDynamicCode ("--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] + [RequiresAssemblyFiles ("--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] + public static void MethodWhichRequires () { } + } + + class TypeWithPublicMethods<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> + { + public TypeWithPublicMethods () { } + } + + [ExpectedWarning ("IL2026", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--")] + [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] + static void TestAccessOnGenericType () + { + new TypeWithPublicMethods (); + } + + 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)] + static void TestAccessOnGenericMethod () + { + MethodWithPublicMethods (); + } + + static void MethodWithPublicMethodsInference<[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] T> (T instance) { } + + // https://github.com/dotnet/runtime/issues/86032 + // IL2026 should be produced by the analyzer as well, but it has a bug around inferred generic arguments + [ExpectedWarning ("IL2026", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.Trimmer | Tool.NativeAot)] + [ExpectedWarning ("IL3002", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] + [ExpectedWarning ("IL3050", "--AccessedThroughGenericParameterAnnotation.TypeWithRequiresMethod.MethodWhichRequires--", ProducedBy = Tool.NativeAot)] + static void TestAccessOnGenericMethodWithInferenceOnMethod () + { + MethodWithPublicMethodsInference (new TypeWithRequiresMethod ()); + } + + public static void Test () + { + TestAccessOnGenericType (); + TestAccessOnGenericMethod (); + TestAccessOnGenericMethodWithInferenceOnMethod (); + } } - // 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)] - [DynamicDependency ("RequiresInDynamicDependency")] - static void TestRequiresInDynamicDependency () + class DynamicDependency { + [RequiresUnreferencedCode ("Message for --RequiresInDynamicDependency--")] + [RequiresAssemblyFiles ("Message for --RequiresInDynamicDependency--")] + [RequiresDynamicCode ("Message for --RequiresInDynamicDependency--")] + 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)] + [DynamicDependency ("RequiresInDynamicDependency")] + public static void Test () + { + } } } } diff --git a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs index 363c089f67f69c..9431505a6ec223 100644 --- a/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs +++ b/src/tools/illink/test/Mono.Linker.Tests/TestCasesRunner/AssemblyChecker.cs @@ -248,7 +248,7 @@ protected virtual void VerifyTypeDefinitionKept (TypeDefinition original, TypeDe VerifyInterfaces (original, linked); VerifyPseudoAttributes (original, linked); - VerifyGenericParameters (original, linked); + VerifyGenericParameters (original, linked, compilerGenerated: false); VerifyCustomAttributes (original, linked); VerifySecurityAttributes (original, linked); @@ -537,12 +537,12 @@ protected virtual void VerifyMethodKept (MethodDefinition src, MethodDefinition Assert.Fail ($"Method `{src.FullName}' should have been kept"); VerifyPseudoAttributes (src, linked); - VerifyGenericParameters (src, linked); + VerifyGenericParameters (src, linked, compilerGenerated); if (!compilerGenerated) { VerifyCustomAttributes (src, linked); VerifyCustomAttributes (src.MethodReturnType, linked.MethodReturnType); } - VerifyParameters (src, linked); + VerifyParameters (src, linked, compilerGenerated); VerifySecurityAttributes (src, linked); VerifyArrayInitializers (src, linked); VerifyMethodBody (src, linked); @@ -1056,7 +1056,7 @@ void VerifyDelegateBackingFields (TypeDefinition src, TypeDefinition linked) } } - void VerifyGenericParameters (IGenericParameterProvider src, IGenericParameterProvider linked) + void VerifyGenericParameters (IGenericParameterProvider src, IGenericParameterProvider linked, bool compilerGenerated) { Assert.AreEqual (src.HasGenericParameters, linked.HasGenericParameters); if (src.HasGenericParameters) { @@ -1064,7 +1064,10 @@ void VerifyGenericParameters (IGenericParameterProvider src, IGenericParameterPr // TODO: Verify constraints var srcp = src.GenericParameters[i]; var lnkp = linked.GenericParameters[i]; - VerifyCustomAttributes (srcp, lnkp); + + if (!compilerGenerated) { + VerifyCustomAttributes (srcp, lnkp); + } if (checkNames) { if (srcp.CustomAttributes.Any (attr => attr.AttributeType.Name == nameof (RemovedNameValueAttribute))) { @@ -1078,7 +1081,7 @@ void VerifyGenericParameters (IGenericParameterProvider src, IGenericParameterPr } } - void VerifyParameters (IMethodSignature src, IMethodSignature linked) + void VerifyParameters (IMethodSignature src, IMethodSignature linked, bool compilerGenerated) { Assert.AreEqual (src.HasParameters, linked.HasParameters); if (src.HasParameters) { @@ -1086,7 +1089,9 @@ void VerifyParameters (IMethodSignature src, IMethodSignature linked) var srcp = src.Parameters[i]; var lnkp = linked.Parameters[i]; - VerifyCustomAttributes (srcp, lnkp); + if (!compilerGenerated) { + VerifyCustomAttributes (srcp, lnkp); + } if (checkNames) { if (srcp.CustomAttributes.Any (attr => attr.AttributeType.Name == nameof (RemovedNameValueAttribute)))